Allow disabling legacy calls and make Voice & Video settings Legacy Voice & Video (#33692)
* Change `feature_group_calls` to default to true. Change state to Beta * Add `enableLegacyCallsVoip` (clarify: Audio settings relate to Legacy) Change `element_call.use_exclusively` to just be the default of `enableLegacyCallsVoip`. Allow disabling in Legacy in the settings. (overwrite `use_exclusivly` via `enableLegacyCallsVoip`) Rename `Voice & Video` to `Legacy Voice & Video` * improvements - settings title update to only show legacy when appropriate - hide menu all together if use_exclusivly is chosen * simplify by removing the feature_group_calls flag * smaller cleanup * fix tests and cleanup * clarify settings (disable) in config.md * add back EC relevant settings in room settings dialog * update screenshots (now default to EC enabled (not disabled) -> show voice and video tab in room settings * update screenshots * always show option to control voice messages input * lint * fix test * disable -> enabled And only have on mic dropdown * update config.md * Back to `disabled` (on by default/no config) * remove element call hint from voice-video settings * Update apps/web/src/i18n/strings/en_EN.json Co-authored-by: Robin <robin@robin.town> * Update apps/web/src/components/views/settings/tabs/user/VoiceUserSettingsTab.tsx Co-authored-by: Robin <robin@robin.town> * review * cleanup element call url setting (its deprecated/not used anymore) * clarify, that also jisti will be enabled/disabled by legacy settings flag * remove double section * remove unn exassary element_call configurations * Update en_EN.json * Update VoiceUserSettingsTab.tsx * Make tests use new defaults (enable element call) * Default events power levels * format * review "Enable Legacy voice/video calls" label * more radical usage of defaults in element_call config.json's * Update config.json * Update en_EN.json * Update RoomSettingsDialog-test.tsx.snap * Update useRoomCall.tsx * fix imports * Update request permission promp to latest designs: https://www.figma.com/design/aOEkaJtaBmPy058V7uoqVr/Element-Call-Updates---2026?node-id=45-12591&t=7takL39icZwt9YjL-0 * Update config.json.d.ts * fix usage of `Element` in i18n * Update General-room-settings-tab-should-be-rendered-properly-1-linux.png --------- Co-authored-by: Robin <robin@robin.town>
This commit is contained in:
@@ -35,7 +35,6 @@ export const DEFAULTS = {
|
||||
preferred_domain: "meet.element.io",
|
||||
},
|
||||
element_call: {
|
||||
use_exclusively: false,
|
||||
brand: "Element Call",
|
||||
},
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ import { PeopleRoomSettingsTab } from "../settings/tabs/room/PeopleRoomSettingsT
|
||||
import { SDKContext } from "../../../contexts/SDKContext";
|
||||
import { type SDKContextClass } from "../../../contexts/SDKContextClass";
|
||||
import { RoomSettingsTab } from "./RoomSettingsDialog-tab.ts";
|
||||
import SdkConfig from "../../../SdkConfig";
|
||||
|
||||
interface IProps {
|
||||
roomId: string;
|
||||
@@ -147,7 +148,7 @@ class RoomSettingsDialog extends React.Component<IProps, IState> {
|
||||
),
|
||||
);
|
||||
}
|
||||
if (SettingsStore.getValue("feature_group_calls")) {
|
||||
if (!SdkConfig.get("element_call").disable) {
|
||||
tabs.push(
|
||||
new Tab(
|
||||
RoomSettingsTab.Voip,
|
||||
|
||||
@@ -18,7 +18,6 @@ import Modal from "../../../../../Modal";
|
||||
import ErrorDialog from "../../../dialogs/ErrorDialog";
|
||||
import PowerSelector from "../../../elements/PowerSelector";
|
||||
import SettingsFieldset from "../../SettingsFieldset";
|
||||
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||
import SdkConfig, { DEFAULTS } from "../../../../../SdkConfig";
|
||||
import { AddPrivilegedUsers } from "../../AddPrivilegedUsers";
|
||||
import SettingsTab from "../SettingsTab";
|
||||
@@ -270,17 +269,14 @@ export default class RolesRoomSettingsTab extends React.Component<IProps, RolesR
|
||||
[EventType.Reaction]: _td("room_settings|permissions|m.reaction"),
|
||||
[EventType.RoomRedaction]: _td("room_settings|permissions|m.room.redaction"),
|
||||
[EventType.RoomPinnedEvents]: _td("room_settings|permissions|m.room.pinned_events"),
|
||||
|
||||
// TODO: Enable support for m.widget event type (https://github.com/vector-im/element-web/issues/13111)
|
||||
"im.vector.modular.widgets": isSpaceRoom ? null : _td("room_settings|permissions|m.widget"),
|
||||
};
|
||||
|
||||
// MSC3401: Native Group VoIP signaling
|
||||
if (SettingsStore.getValue("feature_group_calls")) {
|
||||
if (!SdkConfig.get("element_call").disable) {
|
||||
plEventsToLabels[ElementCallEventType.name] = _td("room_settings|permissions|m.call");
|
||||
plEventsToLabels[ElementCallMemberEventType.name] = _td("room_settings|permissions|m.call.member");
|
||||
}
|
||||
|
||||
const powerLevelDescriptors: Record<string, IPowerLevelDescriptor> = {
|
||||
"users_default": {
|
||||
desc: _t("room_settings|permissions|users_default"),
|
||||
|
||||
@@ -11,7 +11,7 @@ import React, { type ChangeEventHandler, type JSX, type ReactNode } from "react"
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { FALLBACK_ICE_SERVER } from "matrix-js-sdk/src/webrtc/call";
|
||||
import { type EmptyObject } from "matrix-js-sdk/src/matrix";
|
||||
import { Form, SettingsToggleInput } from "@vector-im/compound-web";
|
||||
import { Alert, Form, SettingsToggleInput } from "@vector-im/compound-web";
|
||||
|
||||
import { _t } from "../../../../../languageHandler";
|
||||
import MediaDeviceHandler, { type IMediaDevices, MediaDeviceKindEnum } from "../../../../../MediaDeviceHandler";
|
||||
@@ -19,11 +19,13 @@ import Field from "../../../elements/Field";
|
||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||
import { SettingLevel } from "../../../../../settings/SettingLevel";
|
||||
import SettingsFlag from "../../../elements/SettingsFlag";
|
||||
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||
import { requestMediaPermissions } from "../../../../../utils/media/requestMediaPermissions";
|
||||
import SettingsTab from "../SettingsTab";
|
||||
import { SettingsSection } from "../../shared/SettingsSection";
|
||||
import { SettingsSubsection } from "../../shared/SettingsSubsection";
|
||||
import MatrixClientContext from "../../../../../contexts/MatrixClientContext";
|
||||
import SdkConfig from "../../../../../SdkConfig";
|
||||
|
||||
interface IState {
|
||||
mediaDevices: IMediaDevices | null;
|
||||
@@ -33,6 +35,7 @@ interface IState {
|
||||
audioAutoGainControl: boolean;
|
||||
audioEchoCancellation: boolean;
|
||||
audioNoiseSuppression: boolean;
|
||||
enableLegacyCallsVoip: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,16 +68,29 @@ export default class VoiceUserSettingsTab extends React.Component<EmptyObject, I
|
||||
audioAutoGainControl: MediaDeviceHandler.getAudioAutoGainControl(),
|
||||
audioEchoCancellation: MediaDeviceHandler.getAudioEchoCancellation(),
|
||||
audioNoiseSuppression: MediaDeviceHandler.getAudioNoiseSuppression(),
|
||||
enableLegacyCallsVoip: SettingsStore.getValue("enableLegacyCallsVoip"),
|
||||
};
|
||||
}
|
||||
|
||||
private legacyCallsEnabledWatcherRef: string | undefined;
|
||||
|
||||
public async componentDidMount(): Promise<void> {
|
||||
this.legacyCallsEnabledWatcherRef = SettingsStore.watchSetting(
|
||||
"enableLegacyCallsVoip",
|
||||
null,
|
||||
(...[, , , , value]) => this.setState({ enableLegacyCallsVoip: value as boolean }),
|
||||
);
|
||||
|
||||
const canSeeDeviceLabels = await MediaDeviceHandler.hasAnyLabeledDevices();
|
||||
if (canSeeDeviceLabels) {
|
||||
await this.refreshMediaDevices();
|
||||
}
|
||||
}
|
||||
|
||||
public componentWillUnmount(): void {
|
||||
SettingsStore.unwatchSetting(this.legacyCallsEnabledWatcherRef);
|
||||
}
|
||||
|
||||
private refreshMediaDevices = async (stream?: MediaStream): Promise<void> => {
|
||||
this.setState({
|
||||
mediaDevices: (await MediaDeviceHandler.getDevices()) ?? null,
|
||||
@@ -143,34 +159,46 @@ export default class VoiceUserSettingsTab extends React.Component<EmptyObject, I
|
||||
private onAutoGainChanged: ChangeEventHandler<HTMLInputElement> = async (event) => {
|
||||
const enable = event.target.checked;
|
||||
await MediaDeviceHandler.setAudioAutoGainControl(enable);
|
||||
this.setState({ audioAutoGainControl: MediaDeviceHandler.getAudioAutoGainControl() });
|
||||
this.setState({
|
||||
audioAutoGainControl: MediaDeviceHandler.getAudioAutoGainControl(),
|
||||
});
|
||||
};
|
||||
|
||||
private onNoiseSuppressionChanged: ChangeEventHandler<HTMLInputElement> = async (event) => {
|
||||
const enable = event.target.checked;
|
||||
await MediaDeviceHandler.setAudioNoiseSuppression(enable);
|
||||
this.setState({ audioNoiseSuppression: MediaDeviceHandler.getAudioNoiseSuppression() });
|
||||
this.setState({
|
||||
audioNoiseSuppression: MediaDeviceHandler.getAudioNoiseSuppression(),
|
||||
});
|
||||
};
|
||||
|
||||
private onEchoCancellationChanged: ChangeEventHandler<HTMLInputElement> = async (event) => {
|
||||
const enable = event.target.checked;
|
||||
await MediaDeviceHandler.setAudioEchoCancellation(enable);
|
||||
this.setState({ audioEchoCancellation: MediaDeviceHandler.getAudioEchoCancellation() });
|
||||
this.setState({
|
||||
audioEchoCancellation: MediaDeviceHandler.getAudioEchoCancellation(),
|
||||
});
|
||||
};
|
||||
|
||||
public render(): ReactNode {
|
||||
public render(): JSX.Element {
|
||||
let requestButton: ReactNode | undefined;
|
||||
let speakerDropdown: ReactNode | undefined;
|
||||
let microphoneDropdown: ReactNode | undefined;
|
||||
|
||||
let webcamDropdown: ReactNode | undefined;
|
||||
if (!this.state.mediaDevices) {
|
||||
requestButton = (
|
||||
<div>
|
||||
<p>{_t("settings|voip|missing_permissions_prompt")}</p>
|
||||
<AccessibleButton onClick={this.requestMediaPermissions} kind="primary">
|
||||
{_t("settings|voip|request_permissions")}
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
<Alert
|
||||
type="info"
|
||||
title={_t("settings|voip|permissions")}
|
||||
actions={
|
||||
<AccessibleButton onClick={this.requestMediaPermissions} kind="primary">
|
||||
{_t("settings|voip|request_permissions")}
|
||||
</AccessibleButton>
|
||||
}
|
||||
>
|
||||
{_t("settings|voip|missing_permissions_prompt", { brand: SdkConfig.get("brand") })}
|
||||
</Alert>
|
||||
);
|
||||
} else if (this.state.mediaDevices) {
|
||||
speakerDropdown = this.renderDropdown(
|
||||
@@ -185,6 +213,44 @@ export default class VoiceUserSettingsTab extends React.Component<EmptyObject, I
|
||||
);
|
||||
}
|
||||
|
||||
const elementCallEnabled = !SdkConfig.get("element_call").disable;
|
||||
// We also allow/use legacy if element call is not enabled.
|
||||
const allowLegacyCalls = !SdkConfig.get("element_call").use_exclusively || !elementCallEnabled;
|
||||
const showLegacySettings = this.state.enableLegacyCallsVoip;
|
||||
|
||||
const legacySettingsComponent = (
|
||||
<>
|
||||
<SettingsSubsection heading={_t("settings|voip|voice_section")} stretchContent>
|
||||
{speakerDropdown}
|
||||
<SettingsToggleInput
|
||||
name="voice-auto-gain"
|
||||
label={_t("settings|voip|voice_agc")}
|
||||
checked={this.state.audioAutoGainControl}
|
||||
onChange={this.onAutoGainChanged}
|
||||
/>
|
||||
</SettingsSubsection>
|
||||
<SettingsSubsection heading={_t("settings|voip|video_section")} stretchContent>
|
||||
{webcamDropdown}
|
||||
<SettingsFlag name="VideoView.flipVideoHorizontally" level={SettingLevel.ACCOUNT} />
|
||||
</SettingsSubsection>
|
||||
<SettingsSection heading={_t("common|advanced")}>
|
||||
<SettingsFlag
|
||||
name="webRtcAllowPeerToPeer"
|
||||
level={SettingLevel.DEVICE}
|
||||
onChange={this.changeWebRtcMethod}
|
||||
/>
|
||||
<SettingsFlag
|
||||
name="fallbackICEServerAllowed"
|
||||
label={_t("settings|voip|enable_fallback_ice_server", {
|
||||
server: new URL(FALLBACK_ICE_SERVER).pathname,
|
||||
})}
|
||||
level={SettingLevel.DEVICE}
|
||||
hideIfCannotSet
|
||||
/>
|
||||
</SettingsSection>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<SettingsTab>
|
||||
<Form.Root
|
||||
@@ -193,26 +259,22 @@ export default class VoiceUserSettingsTab extends React.Component<EmptyObject, I
|
||||
evt.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<SettingsSection>
|
||||
<SettingsSection heading={_t("settings|voip|voice_input_section")}>
|
||||
{_t("settings|voip|voice_input_description")}
|
||||
{requestButton}
|
||||
<SettingsSubsection heading={_t("settings|voip|voice_section")} stretchContent>
|
||||
{speakerDropdown}
|
||||
{microphoneDropdown}
|
||||
<SettingsToggleInput
|
||||
name="voice-auto-gain"
|
||||
label={_t("settings|voip|voice_agc")}
|
||||
checked={this.state.audioAutoGainControl}
|
||||
onChange={this.onAutoGainChanged}
|
||||
/>
|
||||
</SettingsSubsection>
|
||||
<SettingsSubsection heading={_t("settings|voip|video_section")} stretchContent>
|
||||
{webcamDropdown}
|
||||
<SettingsFlag name="VideoView.flipVideoHorizontally" level={SettingLevel.ACCOUNT} />
|
||||
</SettingsSubsection>
|
||||
{microphoneDropdown}
|
||||
</SettingsSection>
|
||||
|
||||
<SettingsSection heading={_t("common|advanced")}>
|
||||
<SettingsSubsection heading={_t("settings|voip|voice_processing")}>
|
||||
{allowLegacyCalls && (
|
||||
<SettingsSection heading={_t("common|legacy_voice_and_video_settings")}>
|
||||
{elementCallEnabled && (
|
||||
// allow configuring Legacy calls if EC is also avalibale (otherwise we always show the legacySettingsComponent)
|
||||
<SettingsFlag name="enableLegacyCallsVoip" level={SettingLevel.DEVICE} />
|
||||
)}
|
||||
{(!elementCallEnabled || showLegacySettings) && legacySettingsComponent}
|
||||
</SettingsSection>
|
||||
)}
|
||||
{(allowLegacyCalls || elementCallEnabled) && (
|
||||
<SettingsSection heading={_t("settings|voip|voice_processing")}>
|
||||
<SettingsToggleInput
|
||||
name="voice-noise-suppression"
|
||||
label={_t("settings|voip|noise_suppression")}
|
||||
@@ -227,23 +289,8 @@ export default class VoiceUserSettingsTab extends React.Component<EmptyObject, I
|
||||
checked={this.state.audioEchoCancellation}
|
||||
onChange={this.onEchoCancellationChanged}
|
||||
/>
|
||||
</SettingsSubsection>
|
||||
<SettingsSubsection heading={_t("settings|voip|connection_section")}>
|
||||
<SettingsFlag
|
||||
name="webRtcAllowPeerToPeer"
|
||||
level={SettingLevel.DEVICE}
|
||||
onChange={this.changeWebRtcMethod}
|
||||
/>
|
||||
<SettingsFlag
|
||||
name="fallbackICEServerAllowed"
|
||||
label={_t("settings|voip|enable_fallback_ice_server", {
|
||||
server: new URL(FALLBACK_ICE_SERVER).pathname,
|
||||
})}
|
||||
level={SettingLevel.DEVICE}
|
||||
hideIfCannotSet
|
||||
/>
|
||||
</SettingsSubsection>
|
||||
</SettingsSection>
|
||||
</SettingsSection>
|
||||
)}
|
||||
</Form.Root>
|
||||
</SettingsTab>
|
||||
);
|
||||
|
||||
+21
-10
@@ -45,10 +45,10 @@ import { privateShouldBeEncrypted } from "./utils/rooms";
|
||||
import { shouldForceDisableEncryption } from "./utils/crypto/shouldForceDisableEncryption";
|
||||
import { waitForMember } from "./utils/membership";
|
||||
import { doesRoomVersionSupport, PreferredRoomVersions } from "./utils/PreferredRoomVersions";
|
||||
import SettingsStore from "./settings/SettingsStore";
|
||||
import { MEGOLM_ENCRYPTION_ALGORITHM } from "./utils/crypto";
|
||||
import { ElementCallMemberEventType } from "./call-types";
|
||||
import { htmlSerializeFromMdIfNeeded } from "./editor/serialize";
|
||||
import SdkConfig from "./SdkConfig";
|
||||
|
||||
// we define a number of interfaces which take their names from the js-sdk
|
||||
/* eslint-disable camelcase */
|
||||
@@ -86,15 +86,26 @@ export interface IOpts {
|
||||
joinRule?: JoinRule;
|
||||
}
|
||||
|
||||
const DEFAULT_EVENT_POWER_LEVELS = {
|
||||
[EventType.RoomName]: 50,
|
||||
/**
|
||||
* The power levels set by synapse as of 30.06.2026.
|
||||
* If power_level_content_override is used, these values should be used
|
||||
* as a starting point to ensure the expected room power levels.
|
||||
*
|
||||
* NOTE: power_level_content_override does do a merge but NOT a deep merge.
|
||||
* e.g. "ban": 50, will still be set by the server when `power_level_content_override = {events: {"custom": 0}}`
|
||||
* BUT `events` will lose all the other default props listed below.
|
||||
* So we have to do: `power_level_content_override = {events: {...POWER_LEVEL_EVENTS_DEFAULT, "custom": 0}}`
|
||||
* This is very unfortunate if defaults change in synapse we have to keep the sdk in sync... (todo)
|
||||
*/
|
||||
export const DEFAULT_EVENTS_POWER_LEVEL = {
|
||||
[EventType.RoomAvatar]: 50,
|
||||
[EventType.RoomPowerLevels]: 100,
|
||||
[EventType.RoomHistoryVisibility]: 100,
|
||||
[EventType.RoomCanonicalAlias]: 50,
|
||||
[EventType.RoomTombstone]: 100,
|
||||
[EventType.RoomServerAcl]: 100,
|
||||
[EventType.RoomEncryption]: 100,
|
||||
[EventType.RoomHistoryVisibility]: 100,
|
||||
[EventType.RoomName]: 50,
|
||||
[EventType.RoomPowerLevels]: 100,
|
||||
[EventType.RoomServerAcl]: 100,
|
||||
[EventType.RoomTombstone]: 100,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -173,7 +184,7 @@ export default async function createRoom(client: MatrixClient, opts: IOpts): Pro
|
||||
if (opts.roomType === RoomType.ElementVideo || opts.roomType === RoomType.UnstableCall) {
|
||||
createOpts.power_level_content_override = {
|
||||
events: {
|
||||
...DEFAULT_EVENT_POWER_LEVELS,
|
||||
...DEFAULT_EVENTS_POWER_LEVEL,
|
||||
// Allow all users to send call membership updates
|
||||
[opts.roomType === RoomType.ElementVideo
|
||||
? JitsiCall.MEMBER_EVENT_TYPE
|
||||
@@ -186,10 +197,10 @@ export default async function createRoom(client: MatrixClient, opts: IOpts): Pro
|
||||
},
|
||||
};
|
||||
}
|
||||
} else if (SettingsStore.getValue("feature_group_calls")) {
|
||||
} else if (!SdkConfig.get("element_call").disable) {
|
||||
createOpts.power_level_content_override = {
|
||||
events: {
|
||||
...DEFAULT_EVENT_POWER_LEVELS,
|
||||
...DEFAULT_EVENTS_POWER_LEVEL,
|
||||
// It should always (including non video rooms) be possible to join a group call.
|
||||
[ElementCallMemberEventType.name]: 0,
|
||||
},
|
||||
|
||||
@@ -12,8 +12,7 @@ import { type ReactNode, useCallback, useEffect, useMemo, useState } from "react
|
||||
import { logger as rootLogger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import type React from "react";
|
||||
import { useFeatureEnabled, useSettingValue } from "../useSettings";
|
||||
import SdkConfig from "../../SdkConfig";
|
||||
import { useSettingValue } from "../useSettings";
|
||||
import { useEventEmitter, useEventEmitterState } from "../useEventEmitter";
|
||||
import { LegacyCallHandlerEvent } from "../../LegacyCallHandler";
|
||||
import { useWidgets } from "../../utils/WidgetUtils";
|
||||
@@ -38,6 +37,7 @@ import { type InteractionName } from "../../PosthogTrackers";
|
||||
import { ElementCallMemberEventType } from "../../call-types";
|
||||
import { LocalRoom, LocalRoomState } from "../../models/LocalRoom";
|
||||
import { useScopedRoomContext } from "../../contexts/ScopedRoomContext";
|
||||
import SdkConfig from "../../SdkConfig";
|
||||
import { SDKContextClass } from "../../contexts/SDKContextClass";
|
||||
|
||||
const logger = rootLogger.getChild("useRoomCall");
|
||||
@@ -109,12 +109,13 @@ export const useRoomCall = (
|
||||
} => {
|
||||
const roomViewStore = useScopedRoomContext("roomViewStore").roomViewStore;
|
||||
// settings
|
||||
const groupCallsEnabled = useFeatureEnabled("feature_group_calls");
|
||||
const widgetsFeatureEnabled = useSettingValue(UIFeature.Widgets);
|
||||
const voipFeatureEnabled = useSettingValue(UIFeature.Voip);
|
||||
const useElementCallExclusively = useMemo(() => {
|
||||
const enableLegacyCallsVoip = useSettingValue("enableLegacyCallsVoip");
|
||||
const sdkConfigEcOnly = useMemo(() => {
|
||||
return SdkConfig.get("element_call").use_exclusively;
|
||||
}, []);
|
||||
const useElementCallExclusively = !enableLegacyCallsVoip || sdkConfigEcOnly;
|
||||
|
||||
const serverIsConfiguredForElementCall = useEventEmitterState(
|
||||
CallStore.instance,
|
||||
@@ -175,13 +176,13 @@ export const useRoomCall = (
|
||||
// If there are multiple options, the user will be prompted to choose.
|
||||
const callOptions = useMemo((): PlatformCallType[] => {
|
||||
const options: PlatformCallType[] = [];
|
||||
if (groupCallsEnabled) {
|
||||
if (hasGroupCall || mayCreateElementCalls) {
|
||||
options.push(PlatformCallType.ElementCall);
|
||||
}
|
||||
if (!SdkConfig.get("element_call").disable) {
|
||||
if (useElementCallExclusively && !hasJitsiWidget) {
|
||||
return [PlatformCallType.ElementCall];
|
||||
}
|
||||
if (hasGroupCall || mayCreateElementCalls) {
|
||||
options.push(PlatformCallType.ElementCall);
|
||||
}
|
||||
}
|
||||
if (memberCount <= 2) {
|
||||
options.push(PlatformCallType.LegacyCall);
|
||||
@@ -197,7 +198,6 @@ export const useRoomCall = (
|
||||
memberCount,
|
||||
mayEditWidgets,
|
||||
hasJitsiWidget,
|
||||
groupCallsEnabled,
|
||||
hasGroupCall,
|
||||
mayCreateElementCalls,
|
||||
useElementCallExclusively,
|
||||
|
||||
@@ -495,6 +495,7 @@
|
||||
"integration_manager": "Integration manager",
|
||||
"joined": "Joined",
|
||||
"labs": "Labs",
|
||||
"legacy_voice_and_video_settings": "Matrix 1:1 Calls (Legacy)",
|
||||
"legal": "Legal",
|
||||
"light": "Light",
|
||||
"loading": "Loading…",
|
||||
@@ -1535,7 +1536,6 @@
|
||||
"required_msc_support": "Requires MSC4429 (Profile Updates for Legacy Sync)"
|
||||
},
|
||||
"feature_wysiwyg_composer_description": "Use rich text instead of Markdown in the message composer.",
|
||||
"group_calls": "New group call experience",
|
||||
"group_developer": "Developer",
|
||||
"group_encryption": "Encryption",
|
||||
"group_experimental": "Experimental",
|
||||
@@ -2995,21 +2995,25 @@
|
||||
"audio_output": "Audio Output",
|
||||
"audio_output_empty": "No Audio Outputs detected",
|
||||
"auto_gain_control": "Automatic gain control",
|
||||
"connection_section": "Connection",
|
||||
"dialog_title": "<strong>Settings:</strong> Voice & Video",
|
||||
"echo_cancellation": "Echo cancellation",
|
||||
"echo_cancellation_description": "Removes echo from your microphone input during calls. This setting also applies to Element Call.",
|
||||
"enable_fallback_ice_server": "Allow fallback call assist server (%(server)s)",
|
||||
"enable_fallback_ice_server_description": "Only applies if your homeserver does not offer one. Your IP address would be shared during a call.",
|
||||
"enable_legacy_calls": "Enable Legacy voice/video calls",
|
||||
"enable_legacy_calls_description": "Applies to Jitsi and 1:1 WebRTC calls",
|
||||
"mirror_local_feed": "Mirror local video feed",
|
||||
"missing_permissions_prompt": "Missing media permissions, click the button below to request.",
|
||||
"missing_permissions_prompt": "To participate in calls, give %(brand)s permission to access your audio and video device.",
|
||||
"noise_suppression": "Noise suppression",
|
||||
"noise_suppression_description": "Reduces background noise in your microphone input during calls. This setting also applies to Element Call.",
|
||||
"request_permissions": "Request media permissions",
|
||||
"permissions": "Allow microphone and camera access",
|
||||
"request_permissions": "Request",
|
||||
"title": "Voice & Video",
|
||||
"video_input_empty": "No Webcams detected",
|
||||
"video_section": "Video settings",
|
||||
"voice_agc": "Automatically adjust the microphone volume",
|
||||
"voice_input_description": "The audio input configured here is used for voice messages and calls (Legacy/1:1).",
|
||||
"voice_input_section": "Audio Input",
|
||||
"voice_processing": "Voice processing",
|
||||
"voice_section": "Voice settings"
|
||||
},
|
||||
|
||||
@@ -219,7 +219,6 @@ export interface Settings {
|
||||
"feature_sliding_sync": IBaseSetting<boolean>;
|
||||
"feature_simplified_sliding_sync": IFeature;
|
||||
"feature_element_call_video_rooms": IFeature;
|
||||
"feature_group_calls": IFeature;
|
||||
"feature_disable_call_per_sender_encryption": IFeature;
|
||||
"feature_location_share_live": IFeature;
|
||||
"feature_dynamic_room_predecessors": IFeature;
|
||||
@@ -282,6 +281,7 @@ export interface Settings {
|
||||
"useSystemFont": IBaseSetting<boolean>;
|
||||
"systemFont": IBaseSetting<string>;
|
||||
"webRtcAllowPeerToPeer": IBaseSetting<boolean>;
|
||||
"enableLegacyCallsVoip": IBaseSetting<boolean>;
|
||||
"webrtc_audiooutput": IBaseSetting<string>;
|
||||
"webrtc_audioinput": IBaseSetting<string>;
|
||||
"webrtc_videoinput": IBaseSetting<string>;
|
||||
@@ -587,15 +587,6 @@ export const SETTINGS: Settings = {
|
||||
controller: new ReloadOnChangeController(),
|
||||
default: false,
|
||||
},
|
||||
"feature_group_calls": {
|
||||
isFeature: true,
|
||||
labsGroup: LabGroup.VoiceAndVideo,
|
||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG_PRIORITISED,
|
||||
supportedLevelsAreOrdered: true,
|
||||
displayName: _td("labs|group_calls"),
|
||||
controller: new ReloadOnChangeController(),
|
||||
default: false,
|
||||
},
|
||||
"feature_disable_call_per_sender_encryption": {
|
||||
isFeature: true,
|
||||
labsGroup: LabGroup.VoiceAndVideo,
|
||||
@@ -980,6 +971,12 @@ export const SETTINGS: Settings = {
|
||||
displayName: _td("settings|appearance|custom_font_name"),
|
||||
controller: new SystemFontController(),
|
||||
},
|
||||
"enableLegacyCallsVoip": {
|
||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
||||
displayName: _td("settings|voip|enable_legacy_calls"),
|
||||
description: _td("settings|voip|enable_legacy_calls_description"),
|
||||
default: true,
|
||||
},
|
||||
"webRtcAllowPeerToPeer": {
|
||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
||||
displayName: _td("settings|voip|allow_p2p"),
|
||||
|
||||
@@ -31,7 +31,7 @@ describe("recordClientInformation()", () => {
|
||||
const sdkConfig: DeepReadonly<IConfigOptions> = {
|
||||
...DEFAULTS,
|
||||
brand: "Test Brand",
|
||||
element_call: { use_exclusively: false, brand: "Element Call" },
|
||||
element_call: { brand: "Element Call" },
|
||||
};
|
||||
|
||||
const platform = {
|
||||
|
||||
Reference in New Issue
Block a user