Skip to content

feat(voip): hide video button when feature not active on homeserver #995

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
});
});