diff --git a/src/config/Config.ts b/src/config/Config.ts index 941ffc82..972c9e0c 100644 --- a/src/config/Config.ts +++ b/src/config/Config.ts @@ -5,6 +5,8 @@ SPDX-License-Identifier: AGPL-3.0-only Please see LICENSE in the repository root for full details. */ +import { merge } from "lodash"; + import { getUrlParams } from "../UrlParams"; import { DEFAULT_CONFIG, @@ -15,7 +17,7 @@ import { export class Config { private static internalInstance: Config | undefined; - public static get(): ConfigOptions { + public static get(): ResolvedConfigOptions { if (!this.internalInstance?.config) throw new Error("Config instance read before config got initialized"); return this.internalInstance.config; @@ -29,7 +31,7 @@ export class Config { Config.internalInstance.initPromise = downloadConfig( "../config.json", ).then((config) => { - internalInstance.config = { ...DEFAULT_CONFIG, ...config }; + internalInstance.config = merge({}, DEFAULT_CONFIG, config); }); } return Config.internalInstance.initPromise; diff --git a/src/config/ConfigOptions.ts b/src/config/ConfigOptions.ts index 2fd264ab..4f1ed02a 100644 --- a/src/config/ConfigOptions.ts +++ b/src/config/ConfigOptions.ts @@ -77,6 +77,17 @@ export interface ConfigOptions { * A link to the end-user license agreement (EULA) */ eula: string; + + media_devices?: { + /** + * Defines whether participants should start with audio enabled by default. + */ + enable_audio?: boolean; + /** + * Defines whether participants should start with video enabled by default. + */ + enable_video?: boolean; + }; } // Overrides members from ConfigOptions that are always provided by the @@ -88,6 +99,10 @@ export interface ResolvedConfigOptions extends ConfigOptions { server_name: string; }; }; + media_devices: { + enable_audio: boolean; + enable_video: boolean; + }; } export const DEFAULT_CONFIG: ResolvedConfigOptions = { @@ -98,4 +113,8 @@ export const DEFAULT_CONFIG: ResolvedConfigOptions = { }, }, eula: "https://static.element.io/legal/online-EULA.pdf", + media_devices: { + enable_audio: true, + enable_video: true, + }, }; diff --git a/src/room/MuteStates.ts b/src/room/MuteStates.ts index 80723f01..261be59e 100644 --- a/src/room/MuteStates.ts +++ b/src/room/MuteStates.ts @@ -18,6 +18,7 @@ import { logger } from "matrix-js-sdk/src/logger"; import { MediaDevice, useMediaDevices } from "../livekit/MediaDevicesContext"; import { useReactiveState } from "../useReactiveState"; import { ElementWidgetActions, widget } from "../widget"; +import { Config } from "../config/Config"; /** * If there already are this many participants in the call, we automatically mute @@ -71,8 +72,14 @@ function useMuteState( export function useMuteStates(): MuteStates { const devices = useMediaDevices(); - const audio = useMuteState(devices.audioInput, () => true); - const video = useMuteState(devices.videoInput, () => true); + const audio = useMuteState( + devices.audioInput, + () => Config.get().media_devices.enable_audio, + ); + const video = useMuteState( + devices.videoInput, + () => Config.get().media_devices.enable_video, + ); useEffect(() => { widget?.api.transport diff --git a/src/rtcSessionHelper.test.ts b/src/rtcSessionHelper.test.ts index 8a428661..5a5b7413 100644 --- a/src/rtcSessionHelper.test.ts +++ b/src/rtcSessionHelper.test.ts @@ -10,6 +10,7 @@ import { expect, test, vi } from "vitest"; import { enterRTCSession } from "../src/rtcSessionHelpers"; import { Config } from "../src/config/Config"; +import { DEFAULT_CONFIG } from "./config/ConfigOptions"; test("It joins the correct Session", async () => { const focusFromOlderMembership = { @@ -34,8 +35,8 @@ test("It joins the correct Session", async () => { }; vi.spyOn(Config, "get").mockReturnValue({ + ...DEFAULT_CONFIG, livekit: { livekit_service_url: "http://my-default-service-url.com" }, - eula: "", }); const mockedSession = vi.mocked({ room: {