mirror of
https://github.com/vector-im/element-call.git
synced 2026-03-31 07:00:26 +00:00
Add DeviceMute widget action io.element.device_mute.
This allows to send mute requests ("toWidget") and get the current mute state as a response.
And it will update the client about each change of mute states.
This commit is contained in:
@@ -14,10 +14,12 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { Dispatch, SetStateAction, useMemo } from "react";
|
||||
import { Dispatch, SetStateAction, useEffect, useMemo } from "react";
|
||||
import { IWidgetApiRequest } from "matrix-widget-api";
|
||||
|
||||
import { MediaDevice, useMediaDevices } from "../livekit/MediaDevicesContext";
|
||||
import { useReactiveState } from "../useReactiveState";
|
||||
import { ElementWidgetActions, widget } from "../widget";
|
||||
|
||||
/**
|
||||
* If there already are this many participants in the call, we automatically mute
|
||||
@@ -74,5 +76,52 @@ export function useMuteStates(): MuteStates {
|
||||
const audio = useMuteState(devices.audioInput, () => true);
|
||||
const video = useMuteState(devices.videoInput, () => true);
|
||||
|
||||
useEffect(() => {
|
||||
widget?.api.transport.send(ElementWidgetActions.DeviceMute, {
|
||||
audio_enabled: audio.enabled,
|
||||
video_enabled: video.enabled,
|
||||
});
|
||||
}, [audio, video]);
|
||||
|
||||
useEffect(() => {
|
||||
if (widget) {
|
||||
const onMuteStateChangeRequest = (
|
||||
ev: CustomEvent<IWidgetApiRequest>,
|
||||
): void => {
|
||||
const newState = {
|
||||
audio_enabled: audio.enabled,
|
||||
video_enabled: video.enabled,
|
||||
};
|
||||
if (
|
||||
ev.detail.data.audio_enabled != null &&
|
||||
typeof ev.detail.data.audio_enabled === "boolean"
|
||||
) {
|
||||
audio.setEnabled?.(ev.detail.data.audio_enabled);
|
||||
newState.audio_enabled = ev.detail.data.audio_enabled;
|
||||
}
|
||||
if (
|
||||
ev.detail.data.video_enabled != null &&
|
||||
typeof ev.detail.data.video_enabled === "boolean"
|
||||
) {
|
||||
video.setEnabled?.(ev.detail.data.video_enabled);
|
||||
newState.video_enabled = ev.detail.data.video_enabled;
|
||||
}
|
||||
widget!.api.transport.reply(ev.detail, newState);
|
||||
};
|
||||
|
||||
widget.lazyActions.on(
|
||||
ElementWidgetActions.DeviceMute,
|
||||
onMuteStateChangeRequest,
|
||||
);
|
||||
|
||||
return (): void => {
|
||||
widget!.lazyActions.off(
|
||||
ElementWidgetActions.DeviceMute,
|
||||
onMuteStateChangeRequest,
|
||||
);
|
||||
};
|
||||
}
|
||||
}, [audio, video]);
|
||||
|
||||
return useMemo(() => ({ audio, video }), [audio, video]);
|
||||
}
|
||||
|
||||
@@ -46,6 +46,19 @@ export enum ElementWidgetActions {
|
||||
// host -> Element Call telling EC to stop screen sharing, or that
|
||||
// the user cancelled when selecting a source after a ScreenshareRequest
|
||||
ScreenshareStop = "io.element.screenshare_stop",
|
||||
// This can be sent as form or to widget
|
||||
// fromWidget: updates the client about the current device mute state
|
||||
// toWidget: the client requests a specific device mute configuration
|
||||
// (the reply will always be the resulting configuration)
|
||||
// (it is possible to sent an empty configuration
|
||||
// -> this will allow the client to only get the current state)
|
||||
//
|
||||
// The data of the widget action request and the response are:
|
||||
// {
|
||||
// audio_enabled?: boolean,
|
||||
// video_enabled?: boolean
|
||||
// }
|
||||
DeviceMute = "io.element.device_mute",
|
||||
}
|
||||
|
||||
export interface JoinCallData {
|
||||
@@ -88,6 +101,7 @@ export const widget = ((): WidgetHelpers | null => {
|
||||
ElementWidgetActions.SpotlightLayout,
|
||||
ElementWidgetActions.ScreenshareStart,
|
||||
ElementWidgetActions.ScreenshareStop,
|
||||
ElementWidgetActions.DeviceMute,
|
||||
].forEach((action) => {
|
||||
api.on(`action:${action}`, (ev: CustomEvent<IWidgetApiRequest>) => {
|
||||
ev.preventDefault();
|
||||
|
||||
Reference in New Issue
Block a user