Skip to content

Commit

Permalink
feat(voip): hide video button when feature not active on homeserver
Browse files Browse the repository at this point in the history
  • Loading branch information
marc.sirisak committed May 6, 2024
1 parent 740d598 commit c3608f7
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import LegacyCallViewButtons from "./LegacyCallView/LegacyCallViewButtons";
import { ActionPayload } from "../../../dispatcher/payloads";
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
import TchapUIFeature from "../../../../../../src/tchap/util/TchapUIFeature"; /** :TCHAP: hide-video-button-on-call-screen */

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

// If SDPStreamMetadata isn't supported don't show video mute button in voice calls
const vidMuteButtonShown = call.opponentSupportsSDPStreamMetadata() || call.hasLocalUserMediaVideoTrack;
/** :TCHAP: hide-video-button-on-call-screen */
// const vidMuteButtonShown = call.opponentSupportsSDPStreamMetadata() || call.hasLocalUserMediaVideoTrack;
let vidMuteButtonShown = false // hide by default
if (TchapUIFeature.isFeatureActiveForHomeserver("feature_video_call")) {
vidMuteButtonShown = call.opponentSupportsSDPStreamMetadata() || call.hasLocalUserMediaVideoTrack;
};
/** end :TCHAP: */
// Screensharing is possible, if we can send a second stream and
// identify it using SDPStreamMetadata or if we can replace the already
// existing usermedia track by a screensharing track. We also need to be
Expand Down
6 changes: 6 additions & 0 deletions patches/subtree-modifications.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,11 @@
"src/hooks/useUserOnboardingContext.ts",
"src/hooks/useUserOnboardingTasks.ts"
]
},
"hide-video-button-on-call-screen": {
"issue": "https://github.com/tchapgouv/tchap-web-v4/issues/952",
"files": [
"src/components/views/voip/LegacyCallView.tsx"
]
}
}
142 changes: 142 additions & 0 deletions test/unit-tests/tchap/components/views/voip/LegacyCallView-test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { stubClient } from "matrix-react-sdk/test/test-utils";
import SdkConfig, { ConfigOptions } from "matrix-react-sdk/src/SdkConfig";
import { MatrixClientPeg } from "matrix-react-sdk/src/MatrixClientPeg";
import React from "react";
import { MatrixCall } from "matrix-js-sdk/src/webrtc/call";
import { CallState } from "matrix-js-sdk/src/webrtc/call";
import { fireEvent, render, waitFor } from "@testing-library/react";
import { MatrixClient } from "matrix-js-sdk/src/matrix";

import LegacyCallView from "~matrix-react-sdk/src/components/views/voip/LegacyCallView";
import DMRoomMap from "~matrix-react-sdk/src/utils/DMRoomMap";

describe("LegacyCallView", () => {
const featureName: string = "feature_video_call";
const homeserverName: string = "my.home.server";
const roomId: string = "roomId";
// const fakeCall: MatrixCall = new FakeCall(roomId) as unknown as MatrixCall;
let fakeCall: MatrixCall;

beforeAll(() => {
SdkConfig.reset(); // in case other tests didn't clean up
});

beforeEach(() => {
stubClient();
MatrixClientPeg.getHomeserverName = () => homeserverName;

const mockClient: MatrixClient = MatrixClientPeg.safeGet();
mockClient.isFallbackICEServerAllowed = jest.fn();

const dmRoomMap = new DMRoomMap(mockClient);

jest.spyOn(dmRoomMap, "getUserIdForRoomId");
jest.spyOn(DMRoomMap, "shared").mockReturnValue(dmRoomMap);

fakeCall = new MatrixCall({
client: mockClient,
roomId,
});

jest.spyOn(fakeCall, "state", "get").mockReturnValue(CallState.Connected);
jest.spyOn(fakeCall, "isLocalOnHold").mockReturnValue(false);
jest.spyOn(fakeCall, "isRemoteOnHold").mockReturnValue(false);
jest.spyOn(fakeCall, "isMicrophoneMuted").mockReturnValue(false);
jest.spyOn(fakeCall, "isLocalVideoMuted").mockReturnValue(true);
jest.spyOn(fakeCall, "isScreensharing").mockReturnValue(false);
jest.spyOn(fakeCall, "isScreensharing").mockReturnValue(false);
});

afterEach(function () {
SdkConfig.reset(); // we touch the config, so clean up
jest.clearAllMocks();
});

const mockFeatureConfig = (homeservers: string[]) => {
// mock SdkConfig.get("tchap_features")
const config: ConfigOptions = { tchap_features: {} };
config.tchap_features[featureName] = homeservers;
SdkConfig.put(config);
};

const renderCallView = () => {
return render(
<LegacyCallView
key="call-view"
onMouseDownOnHeader={() => null}
call={fakeCall}
secondaryCall={fakeCall}
pipMode={false}
onResize={() => null}
/>,
);
};

it("returns true when the the homeserver include video_call feature", () => {
jest.spyOn(fakeCall, "opponentSupportsSDPStreamMetadata").mockReturnValue(true);

mockFeatureConfig([homeserverName]);
const { container } = renderCallView();

// needs to hover on the component to make the control button appears
fireEvent.mouseEnter(container);
waitFor(() => container.getElementsByClassName("mx_LegacyCallViewButtons").length);

expect(container.getElementsByClassName("mx_LegacyCallViewButtons_button_vid").length).toBe(1);
});

it("returns false when the the homeserver doesnt include video_call feature", async () => {
jest.spyOn(fakeCall, "opponentSupportsSDPStreamMetadata").mockReturnValue(true);

mockFeatureConfig(["other.homeserver"]);
const { container } = renderCallView();

// needs to hover on the component to make the control button appears
fireEvent.mouseEnter(container);
waitFor(() => container.getElementsByClassName("mx_LegacyCallViewButtons").length);

expect(container.getElementsByClassName("mx_LegacyCallViewButtons_button_vid").length).toBe(0);
});

it("returns false when the call doesnt support opponentSupportsSDPStreamMetadata or hasLocalUserMediaVideoTrack", async () => {
jest.spyOn(fakeCall, "opponentSupportsSDPStreamMetadata").mockReturnValue(false);
jest.spyOn(fakeCall, "hasLocalUserMediaVideoTrack", "get").mockReturnValue(false);

mockFeatureConfig([homeserverName]);
const { container } = renderCallView();

// needs to hover on the component to make the control button appears
fireEvent.mouseEnter(container);
waitFor(() => container.getElementsByClassName("mx_LegacyCallViewButtons").length);

expect(container.getElementsByClassName("mx_LegacyCallViewButtons_button_vid").length).toBe(0);
});

it("returns true when the call support opponentSupportsSDPStreamMetadata", async () => {
jest.spyOn(fakeCall, "opponentSupportsSDPStreamMetadata").mockReturnValue(true);
jest.spyOn(fakeCall, "hasLocalUserMediaVideoTrack", "get").mockReturnValue(false);

mockFeatureConfig([homeserverName]);
const { container } = renderCallView();

// needs to hover on the component to make the control button appears
fireEvent.mouseEnter(container);
waitFor(() => container.getElementsByClassName("mx_LegacyCallViewButtons").length);

expect(container.getElementsByClassName("mx_LegacyCallViewButtons_button_vid").length).toBe(1);
});

it("returns true when the call support hasLocalUserMediaVideoTrack", async () => {
jest.spyOn(fakeCall, "opponentSupportsSDPStreamMetadata").mockReturnValue(false);
jest.spyOn(fakeCall, "hasLocalUserMediaVideoTrack", "get").mockReturnValue(true);

mockFeatureConfig([homeserverName]);
const { container } = renderCallView();

// needs to hover on the component to make the control button appears
fireEvent.mouseEnter(container);
waitFor(() => container.getElementsByClassName("mx_LegacyCallViewButtons").length);

expect(container.getElementsByClassName("mx_LegacyCallViewButtons_button_vid").length).toBe(1);
});
});

0 comments on commit c3608f7

Please sign in to comment.