Hide voip buttons in group rooms in environments with widgets disabled (#12664)

* Hide voip buttons in group rooms in environments with widgets disabled

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Fix test stubs

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski 2024-06-21 09:42:50 +01:00 committed by GitHub
parent 5bcf76c9ab
commit 2d8c23e806
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 79 additions and 23 deletions

View file

@ -83,6 +83,7 @@ export default function RoomHeader({
hasActiveCallSession, hasActiveCallSession,
callOptions, callOptions,
showVoiceCallButton, showVoiceCallButton,
showVideoCallButton,
} = useRoomCall(room); } = useRoomCall(room);
const groupCallsEnabled = useFeatureEnabled("feature_group_calls"); const groupCallsEnabled = useFeatureEnabled("feature_group_calls");
@ -200,25 +201,20 @@ export default function RoomHeader({
)} )}
</> </>
); );
let voiceCallButton: JSX.Element | undefined = (
let voiceCallButton: JSX.Element | undefined; <Tooltip label={voiceCallDisabledReason ?? _t("voip|voice_call")}>
if (showVoiceCallButton) { <IconButton
voiceCallButton = ( // We need both: isViewingCall and isConnectedToCall
<Tooltip label={voiceCallDisabledReason ?? _t("voip|voice_call")}> // - in the Lobby we are viewing a call but are not connected to it.
<IconButton // - in pip view we are connected to the call but not viewing it.
// We need both: isViewingCall and isConnectedToCall disabled={!!voiceCallDisabledReason || isViewingCall || isConnectedToCall}
// - in the Lobby we are viewing a call but are not connected to it. aria-label={voiceCallDisabledReason ?? _t("voip|voice_call")}
// - in pip view we are connected to the call but not viewing it. onClick={(ev) => voiceCallClick(ev, callOptions[0])}
disabled={!!voiceCallDisabledReason || isViewingCall || isConnectedToCall} >
aria-label={voiceCallDisabledReason ?? _t("voip|voice_call")} <VoiceCallIcon />
onClick={(ev) => voiceCallClick(ev, callOptions[0])} </IconButton>
> </Tooltip>
<VoiceCallIcon /> );
</IconButton>
</Tooltip>
);
}
const closeLobbyButton = ( const closeLobbyButton = (
<Tooltip label={_t("voip|close_lobby")}> <Tooltip label={_t("voip|close_lobby")}>
<IconButton onClick={toggleCall} aria-label={_t("voip|close_lobby")}> <IconButton onClick={toggleCall} aria-label={_t("voip|close_lobby")}>
@ -226,13 +222,20 @@ export default function RoomHeader({
</IconButton> </IconButton>
</Tooltip> </Tooltip>
); );
let videoCallButton = startVideoCallButton; let videoCallButton: JSX.Element | undefined = startVideoCallButton;
if (isConnectedToCall) { if (isConnectedToCall) {
videoCallButton = toggleCallButton; videoCallButton = toggleCallButton;
} else if (isViewingCall) { } else if (isViewingCall) {
videoCallButton = closeLobbyButton; videoCallButton = closeLobbyButton;
} }
if (!showVideoCallButton) {
videoCallButton = undefined;
}
if (!showVoiceCallButton) {
voiceCallButton = undefined;
}
return ( return (
<> <>
<Flex as="header" align="center" gap="var(--cpd-space-3x)" className="mx_RoomHeader light-panel"> <Flex as="header" align="center" gap="var(--cpd-space-3x)" className="mx_RoomHeader light-panel">

View file

@ -41,6 +41,8 @@ import { Action } from "../../dispatcher/actions";
import { CallStore, CallStoreEvent } from "../../stores/CallStore"; import { CallStore, CallStoreEvent } from "../../stores/CallStore";
import { isVideoRoom } from "../../utils/video-rooms"; import { isVideoRoom } from "../../utils/video-rooms";
import { useGuestAccessInformation } from "./useGuestAccessInformation"; import { useGuestAccessInformation } from "./useGuestAccessInformation";
import SettingsStore from "../../settings/SettingsStore";
import { UIFeature } from "../../settings/UIFeature";
export enum PlatformCallType { export enum PlatformCallType {
ElementCall, ElementCall,
@ -83,6 +85,7 @@ export const useRoomCall = (
isConnectedToCall: boolean; isConnectedToCall: boolean;
hasActiveCallSession: boolean; hasActiveCallSession: boolean;
callOptions: PlatformCallType[]; callOptions: PlatformCallType[];
showVideoCallButton: boolean;
showVoiceCallButton: boolean; showVoiceCallButton: boolean;
} => { } => {
// settings // settings
@ -268,8 +271,14 @@ export const useRoomCall = (
}, [isViewingCall, room.roomId]); }, [isViewingCall, room.roomId]);
// We hide the voice call button if it'd have the same effect as the video call button // We hide the voice call button if it'd have the same effect as the video call button
const hideVoiceCallButton = let hideVoiceCallButton =
isManagedHybridWidgetEnabled(room.roomId) || !callOptions.includes(PlatformCallType.LegacyCall); isManagedHybridWidgetEnabled(room.roomId) || !callOptions.includes(PlatformCallType.LegacyCall);
let hideVideoCallButton = false;
// We hide both buttons if they require widgets but widgets are disabled.
if (memberCount > 2 && !SettingsStore.getValue(UIFeature.Widgets)) {
hideVoiceCallButton = true;
hideVideoCallButton = true;
}
/** /**
* We've gone through all the steps * We've gone through all the steps
@ -285,5 +294,6 @@ export const useRoomCall = (
hasActiveCallSession: hasActiveCallSession, hasActiveCallSession: hasActiveCallSession,
callOptions, callOptions,
showVoiceCallButton: !hideVoiceCallButton, showVoiceCallButton: !hideVoiceCallButton,
showVideoCallButton: !hideVideoCallButton,
}; };
}; };

View file

@ -61,6 +61,7 @@ import { _t } from "../../../../src/languageHandler";
import * as UseCall from "../../../../src/hooks/useCall"; import * as UseCall from "../../../../src/hooks/useCall";
import { SdkContextClass } from "../../../../src/contexts/SDKContext"; import { SdkContextClass } from "../../../../src/contexts/SDKContext";
import WidgetStore, { IApp } from "../../../../src/stores/WidgetStore"; import WidgetStore, { IApp } from "../../../../src/stores/WidgetStore";
import { UIFeature } from "../../../../src/settings/UIFeature";
jest.mock("../../../../src/utils/ShieldUtils"); jest.mock("../../../../src/utils/ShieldUtils");
@ -255,7 +256,47 @@ describe("RoomHeader", () => {
expect(queryByLabelText(container, "Voice call")).not.toBeInTheDocument(); expect(queryByLabelText(container, "Voice call")).not.toBeInTheDocument();
}); });
describe("UIFeature.Widgets enabled (default)", () => {
beforeEach(() => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((feature) => feature == UIFeature.Widgets);
});
it("should show call buttons in a room with 2 members", () => {
mockRoomMembers(room, 2);
const { container } = render(<RoomHeader room={room} />, getWrapper());
expect(getByLabelText(container, "Video call")).toBeInTheDocument();
});
it("should show call buttons in a room with more than 2 members", () => {
mockRoomMembers(room, 3);
const { container } = render(<RoomHeader room={room} />, getWrapper());
expect(getByLabelText(container, "Video call")).toBeInTheDocument();
});
});
describe("UIFeature.Widgets disabled", () => {
beforeEach(() => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((feature) => false);
});
it("should show call buttons in a room with 2 members", () => {
mockRoomMembers(room, 2);
const { container } = render(<RoomHeader room={room} />, getWrapper());
expect(getByLabelText(container, "Video call")).toBeInTheDocument();
});
it("should not show call buttons in a room with more than 2 members", () => {
mockRoomMembers(room, 3);
const { container } = render(<RoomHeader room={room} />, getWrapper());
expect(queryByLabelText(container, "Video call")).not.toBeInTheDocument();
});
});
describe("groups call disabled", () => { describe("groups call disabled", () => {
beforeEach(() => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((feature) => feature == UIFeature.Widgets);
});
it("you can't call if you're alone", () => { it("you can't call if you're alone", () => {
mockRoomMembers(room, 1); mockRoomMembers(room, 1);
const { container } = render(<RoomHeader room={room} />, getWrapper()); const { container } = render(<RoomHeader room={room} />, getWrapper());
@ -313,7 +354,9 @@ describe("RoomHeader", () => {
describe("group call enabled", () => { describe("group call enabled", () => {
beforeEach(() => { beforeEach(() => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((feature) => feature === "feature_group_calls"); jest.spyOn(SettingsStore, "getValue").mockImplementation(
(feature) => feature === "feature_group_calls" || feature == UIFeature.Widgets,
);
}); });
it("renders only the video call element", async () => { it("renders only the video call element", async () => {
@ -353,7 +396,7 @@ describe("RoomHeader", () => {
it("clicking on ongoing (unpinned) call re-pins it", () => { it("clicking on ongoing (unpinned) call re-pins it", () => {
mockRoomMembers(room, 3); mockRoomMembers(room, 3);
jest.spyOn(SettingsStore, "getValue").mockReturnValue(false); jest.spyOn(SettingsStore, "getValue").mockImplementation((feature) => feature == UIFeature.Widgets);
// allow calls // allow calls
jest.spyOn(room.currentState, "mayClientSendStateEvent").mockReturnValue(true); jest.spyOn(room.currentState, "mayClientSendStateEvent").mockReturnValue(true);
jest.spyOn(WidgetLayoutStore.instance, "isInContainer").mockReturnValue(false); jest.spyOn(WidgetLayoutStore.instance, "isInContainer").mockReturnValue(false);