mirror of https://github.com/vector-im/riot-web
Merge pull request #27858 from element-hq/t3chguy/fix-jitsi
Fix Jitsi by updating device mute updates over postMessage APIpull/27881/head
commit
31345ddd36
|
@ -34,7 +34,6 @@ import type {
|
||||||
JitsiMeetExternalAPIConstructor,
|
JitsiMeetExternalAPIConstructor,
|
||||||
ExternalAPIEventCallbacks,
|
ExternalAPIEventCallbacks,
|
||||||
JitsiMeetExternalAPI as _JitsiMeetExternalAPI,
|
JitsiMeetExternalAPI as _JitsiMeetExternalAPI,
|
||||||
AudioMuteStatusChangedEvent,
|
|
||||||
LogEvent,
|
LogEvent,
|
||||||
VideoMuteStatusChangedEvent,
|
VideoMuteStatusChangedEvent,
|
||||||
ExternalAPIOptions as _ExternalAPIOptions,
|
ExternalAPIOptions as _ExternalAPIOptions,
|
||||||
|
@ -103,6 +102,14 @@ let widgetApi: WidgetApi | undefined;
|
||||||
let meetApi: _JitsiMeetExternalAPI | undefined;
|
let meetApi: _JitsiMeetExternalAPI | undefined;
|
||||||
let skipOurWelcomeScreen = false;
|
let skipOurWelcomeScreen = false;
|
||||||
|
|
||||||
|
async function checkAudioVideoEnabled(): Promise<[audioEnabled: boolean, videoEnabled: boolean]> {
|
||||||
|
if (!meetApi) return [false, false];
|
||||||
|
const [audioEnabled, videoEnabled] = (await Promise.all([meetApi.isAudioMuted(), meetApi.isVideoMuted()])).map(
|
||||||
|
(muted) => !muted,
|
||||||
|
);
|
||||||
|
return [audioEnabled, videoEnabled];
|
||||||
|
}
|
||||||
|
|
||||||
const setupCompleted = (async (): Promise<string | void> => {
|
const setupCompleted = (async (): Promise<string | void> => {
|
||||||
try {
|
try {
|
||||||
// Queue a config.json lookup asap, so we can use it later on. We want this to be concurrent with
|
// Queue a config.json lookup asap, so we can use it later on. We want this to be concurrent with
|
||||||
|
@ -159,7 +166,7 @@ const setupCompleted = (async (): Promise<string | void> => {
|
||||||
|
|
||||||
const handleAction = (
|
const handleAction = (
|
||||||
action: WidgetApiAction,
|
action: WidgetApiAction,
|
||||||
handler: (request: IWidgetApiRequestData) => Promise<void>,
|
handler: (request: IWidgetApiRequestData) => Promise<IWidgetApiResponseData | void>,
|
||||||
): void => {
|
): void => {
|
||||||
widgetApi!.on(`action:${action}`, async (ev: CustomEvent<IWidgetApiRequest>) => {
|
widgetApi!.on(`action:${action}`, async (ev: CustomEvent<IWidgetApiRequest>) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
@ -167,8 +174,7 @@ const setupCompleted = (async (): Promise<string | void> => {
|
||||||
|
|
||||||
let response: IWidgetApiResponseData;
|
let response: IWidgetApiResponseData;
|
||||||
try {
|
try {
|
||||||
await handler(ev.detail.data);
|
response = (await handler(ev.detail.data)) ?? {};
|
||||||
response = {};
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error) {
|
if (e instanceof Error) {
|
||||||
response = { error: { message: e.message } };
|
response = { error: { message: e.message } };
|
||||||
|
@ -194,25 +200,26 @@ const setupCompleted = (async (): Promise<string | void> => {
|
||||||
meetApi?.executeCommand("hangup");
|
meetApi?.executeCommand("hangup");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
handleAction(ElementWidgetActions.MuteAudio, async () => {
|
handleAction(ElementWidgetActions.DeviceMute, async (params) => {
|
||||||
if (meetApi && !(await meetApi.isAudioMuted())) {
|
if (!meetApi) return;
|
||||||
|
|
||||||
|
const [audioEnabled, videoEnabled] = await checkAudioVideoEnabled();
|
||||||
|
|
||||||
|
if (Object.keys(params).length === 0) {
|
||||||
|
// Handle query
|
||||||
|
return {
|
||||||
|
audio_enabled: audioEnabled,
|
||||||
|
video_enabled: videoEnabled,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.audio_enabled !== audioEnabled) {
|
||||||
meetApi.executeCommand("toggleAudio");
|
meetApi.executeCommand("toggleAudio");
|
||||||
}
|
}
|
||||||
});
|
if (params.video_enabled !== videoEnabled) {
|
||||||
handleAction(ElementWidgetActions.UnmuteAudio, async () => {
|
|
||||||
if (meetApi && (await meetApi.isAudioMuted())) {
|
|
||||||
meetApi.executeCommand("toggleAudio");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
handleAction(ElementWidgetActions.MuteVideo, async () => {
|
|
||||||
if (meetApi && !(await meetApi.isVideoMuted())) {
|
|
||||||
meetApi.executeCommand("toggleVideo");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
handleAction(ElementWidgetActions.UnmuteVideo, async () => {
|
|
||||||
if (meetApi && (await meetApi.isVideoMuted())) {
|
|
||||||
meetApi.executeCommand("toggleVideo");
|
meetApi.executeCommand("toggleVideo");
|
||||||
}
|
}
|
||||||
|
return params;
|
||||||
});
|
});
|
||||||
handleAction(ElementWidgetActions.TileLayout, async () => {
|
handleAction(ElementWidgetActions.TileLayout, async () => {
|
||||||
meetApi?.executeCommand("setTileView", true);
|
meetApi?.executeCommand("setTileView", true);
|
||||||
|
@ -473,7 +480,7 @@ async function joinConference(audioInput?: string | null, videoInput?: string |
|
||||||
meetApi.on("videoConferenceLeft", onVideoConferenceLeft);
|
meetApi.on("videoConferenceLeft", onVideoConferenceLeft);
|
||||||
meetApi.on("readyToClose", closeConference as ExternalAPIEventCallbacks["readyToClose"]);
|
meetApi.on("readyToClose", closeConference as ExternalAPIEventCallbacks["readyToClose"]);
|
||||||
meetApi.on("errorOccurred", onErrorOccurred);
|
meetApi.on("errorOccurred", onErrorOccurred);
|
||||||
meetApi.on("audioMuteStatusChanged", onAudioMuteStatusChanged);
|
meetApi.on("audioMuteStatusChanged", onMuteStatusChanged);
|
||||||
meetApi.on("videoMuteStatusChanged", onVideoMuteStatusChanged);
|
meetApi.on("videoMuteStatusChanged", onVideoMuteStatusChanged);
|
||||||
|
|
||||||
(["videoConferenceJoined", "participantJoined", "participantLeft"] as const).forEach((event) => {
|
(["videoConferenceJoined", "participantJoined", "participantLeft"] as const).forEach((event) => {
|
||||||
|
@ -523,9 +530,13 @@ const onErrorOccurred = ({ error }: Parameters<ExternalAPIEventCallbacks["errorO
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onAudioMuteStatusChanged = ({ muted }: AudioMuteStatusChangedEvent): void => {
|
const onMuteStatusChanged = async (): Promise<void> => {
|
||||||
const action = muted ? ElementWidgetActions.MuteAudio : ElementWidgetActions.UnmuteAudio;
|
if (!meetApi) return;
|
||||||
void widgetApi?.transport.send(action, {});
|
const [audioEnabled, videoEnabled] = await checkAudioVideoEnabled();
|
||||||
|
void widgetApi?.transport.send(ElementWidgetActions.DeviceMute, {
|
||||||
|
audio_enabled: audioEnabled,
|
||||||
|
video_enabled: videoEnabled,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onVideoMuteStatusChanged = ({ muted }: VideoMuteStatusChangedEvent): void => {
|
const onVideoMuteStatusChanged = ({ muted }: VideoMuteStatusChangedEvent): void => {
|
||||||
|
@ -534,11 +545,9 @@ const onVideoMuteStatusChanged = ({ muted }: VideoMuteStatusChangedEvent): void
|
||||||
// hanging up, which we need to ignore by padding the timeout here,
|
// hanging up, which we need to ignore by padding the timeout here,
|
||||||
// otherwise the React SDK will mistakenly think the user turned off
|
// otherwise the React SDK will mistakenly think the user turned off
|
||||||
// their video by hand
|
// their video by hand
|
||||||
setTimeout(() => {
|
setTimeout(() => onMuteStatusChanged, 200);
|
||||||
if (meetApi) void widgetApi?.transport.send(ElementWidgetActions.MuteVideo, {});
|
|
||||||
}, 200);
|
|
||||||
} else {
|
} else {
|
||||||
void widgetApi?.transport.send(ElementWidgetActions.UnmuteVideo, {});
|
void onMuteStatusChanged();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue