Connect to Jitsi unmuted by default (#22660)
* Connect to Jitsi unmuted by default * Refactor joinConference to placate SonarQube
This commit is contained in:
parent
9eda502a9b
commit
5f176fa9a6
1 changed files with 82 additions and 70 deletions
|
@ -146,7 +146,7 @@ const ack = (ev: CustomEvent<IWidgetApiRequest>) => widgetApi.transport.reply(ev
|
||||||
widgetApi.on(`action:${ElementWidgetActions.JoinCall}`,
|
widgetApi.on(`action:${ElementWidgetActions.JoinCall}`,
|
||||||
(ev: CustomEvent<IWidgetApiRequest>) => {
|
(ev: CustomEvent<IWidgetApiRequest>) => {
|
||||||
const { audioDevice, videoDevice } = ev.detail.data;
|
const { audioDevice, videoDevice } = ev.detail.data;
|
||||||
joinConference(audioDevice as string, videoDevice as string);
|
joinConference(audioDevice as string | null, videoDevice as string | null);
|
||||||
ack(ev);
|
ack(ev);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -322,7 +322,11 @@ function closeConference() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// event handler bound in HTML
|
// event handler bound in HTML
|
||||||
function joinConference(audioDevice?: string, videoDevice?: string) {
|
// An audio device of undefined instructs Jitsi to start unmuted with whatever
|
||||||
|
// audio device it can find, while a device of null instructs it to start muted,
|
||||||
|
// and a non-nullish device specifies the label of a specific device to use.
|
||||||
|
// Same for video devices.
|
||||||
|
function joinConference(audioDevice?: string | null, videoDevice?: string | null) {
|
||||||
let jwt;
|
let jwt;
|
||||||
if (jitsiAuth === JITSI_OPENIDTOKEN_JWT_AUTH) {
|
if (jitsiAuth === JITSI_OPENIDTOKEN_JWT_AUTH) {
|
||||||
if (!openIdToken?.access_token) { // eslint-disable-line camelcase
|
if (!openIdToken?.access_token) { // eslint-disable-line camelcase
|
||||||
|
@ -364,8 +368,8 @@ function joinConference(audioDevice?: string, videoDevice?: string) {
|
||||||
configOverwrite: {
|
configOverwrite: {
|
||||||
subject: roomName,
|
subject: roomName,
|
||||||
startAudioOnly,
|
startAudioOnly,
|
||||||
startWithAudioMuted: audioDevice == null,
|
startWithAudioMuted: audioDevice === null,
|
||||||
startWithVideoMuted: videoDevice == null,
|
startWithVideoMuted: videoDevice === null,
|
||||||
// Request some log levels for inclusion in rageshakes
|
// Request some log levels for inclusion in rageshakes
|
||||||
// Ideally we would capture all possible log levels, but this can
|
// Ideally we would capture all possible log levels, but this can
|
||||||
// cause Jitsi Meet to try to post various circular data structures
|
// cause Jitsi Meet to try to post various circular data structures
|
||||||
|
@ -393,76 +397,84 @@ function joinConference(audioDevice?: string, videoDevice?: string) {
|
||||||
|
|
||||||
// fires once when user joins the conference
|
// fires once when user joins the conference
|
||||||
// (regardless of video on or off)
|
// (regardless of video on or off)
|
||||||
meetApi.on("videoConferenceJoined", () => {
|
meetApi.on("videoConferenceJoined", onVideoConferenceJoined);
|
||||||
// Although we set our displayName with the userInfo option above, that
|
meetApi.on("videoConferenceLeft", onVideoConferenceLeft);
|
||||||
// option has a bug where it causes the name to be the HTML encoding of
|
|
||||||
// what was actually intended. So, we use the displayName command to at
|
|
||||||
// least ensure that the name is correct after entering the meeting.
|
|
||||||
// https://github.com/jitsi/jitsi-meet/issues/11664
|
|
||||||
// We can't just use these commands immediately after creating the
|
|
||||||
// iframe, because there's *another* bug where they can crash Jitsi by
|
|
||||||
// racing with its startup process.
|
|
||||||
if (displayName) meetApi.executeCommand("displayName", displayName);
|
|
||||||
// This doesn't have a userInfo equivalent, so has to be set via commands
|
|
||||||
if (avatarUrl) meetApi.executeCommand("avatarUrl", avatarUrl);
|
|
||||||
|
|
||||||
if (widgetApi) {
|
|
||||||
// ignored promise because we don't care if it works
|
|
||||||
// noinspection JSIgnoredPromiseFromCall
|
|
||||||
widgetApi.setAlwaysOnScreen(true);
|
|
||||||
widgetApi.transport.send(ElementWidgetActions.JoinCall, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Video rooms should start in tile mode
|
|
||||||
if (isVideoChannel) meetApi.executeCommand("setTileView", true);
|
|
||||||
});
|
|
||||||
|
|
||||||
meetApi.on("videoConferenceLeft", () => {
|
|
||||||
notifyHangup();
|
|
||||||
meetApi = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
meetApi.on("readyToClose", closeConference);
|
meetApi.on("readyToClose", closeConference);
|
||||||
|
meetApi.on("errorOccurred", onErrorOccurred);
|
||||||
meetApi.on("errorOccurred", ({ error }) => {
|
meetApi.on("audioMuteStatusChanged", onAudioMuteStatusChanged);
|
||||||
if (error.isFatal) {
|
meetApi.on("videoMuteStatusChanged", onVideoMuteStatusChanged);
|
||||||
// We got disconnected. Since Jitsi Meet might send us back to the
|
|
||||||
// prejoin screen, we're forced to act as if we hung up entirely.
|
|
||||||
notifyHangup(error.message);
|
|
||||||
meetApi = null;
|
|
||||||
closeConference();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
meetApi.on("audioMuteStatusChanged", ({ muted }) => {
|
|
||||||
const action = muted ? ElementWidgetActions.MuteAudio : ElementWidgetActions.UnmuteAudio;
|
|
||||||
widgetApi?.transport.send(action, {});
|
|
||||||
});
|
|
||||||
|
|
||||||
meetApi.on("videoMuteStatusChanged", ({ muted }) => {
|
|
||||||
if (muted) {
|
|
||||||
// Jitsi Meet always sends a "video muted" event directly before
|
|
||||||
// hanging up, which we need to ignore by padding the timeout here,
|
|
||||||
// otherwise the React SDK will mistakenly think the user turned off
|
|
||||||
// their video by hand
|
|
||||||
setTimeout(() => {
|
|
||||||
if (meetApi) widgetApi?.transport.send(ElementWidgetActions.MuteVideo, {});
|
|
||||||
}, 200);
|
|
||||||
} else {
|
|
||||||
widgetApi?.transport.send(ElementWidgetActions.UnmuteVideo, {});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
["videoConferenceJoined", "participantJoined", "participantLeft"].forEach(event => {
|
["videoConferenceJoined", "participantJoined", "participantLeft"].forEach(event => {
|
||||||
meetApi.on(event, () => {
|
meetApi.on(event, updateParticipants);
|
||||||
widgetApi?.transport.send(ElementWidgetActions.CallParticipants, {
|
|
||||||
participants: meetApi.getParticipantsInfo(),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Patch logs into rageshakes
|
// Patch logs into rageshakes
|
||||||
meetApi.on("log", ({ logLevel, args }) =>
|
meetApi.on("log", onLog);
|
||||||
(parent as unknown as typeof global).mx_rage_logger?.log(logLevel, ...args),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onVideoConferenceJoined = () => {
|
||||||
|
// Although we set our displayName with the userInfo option above, that
|
||||||
|
// option has a bug where it causes the name to be the HTML encoding of
|
||||||
|
// what was actually intended. So, we use the displayName command to at
|
||||||
|
// least ensure that the name is correct after entering the meeting.
|
||||||
|
// https://github.com/jitsi/jitsi-meet/issues/11664
|
||||||
|
// We can't just use these commands immediately after creating the
|
||||||
|
// iframe, because there's *another* bug where they can crash Jitsi by
|
||||||
|
// racing with its startup process.
|
||||||
|
if (displayName) meetApi.executeCommand("displayName", displayName);
|
||||||
|
// This doesn't have a userInfo equivalent, so has to be set via commands
|
||||||
|
if (avatarUrl) meetApi.executeCommand("avatarUrl", avatarUrl);
|
||||||
|
|
||||||
|
if (widgetApi) {
|
||||||
|
// ignored promise because we don't care if it works
|
||||||
|
// noinspection JSIgnoredPromiseFromCall
|
||||||
|
widgetApi.setAlwaysOnScreen(true);
|
||||||
|
widgetApi.transport.send(ElementWidgetActions.JoinCall, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Video rooms should start in tile mode
|
||||||
|
if (isVideoChannel) meetApi.executeCommand("setTileView", true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onVideoConferenceLeft = () => {
|
||||||
|
notifyHangup();
|
||||||
|
meetApi = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onErrorOccurred = ({ error }) => {
|
||||||
|
if (error.isFatal) {
|
||||||
|
// We got disconnected. Since Jitsi Meet might send us back to the
|
||||||
|
// prejoin screen, we're forced to act as if we hung up entirely.
|
||||||
|
notifyHangup(error.message);
|
||||||
|
meetApi = null;
|
||||||
|
closeConference();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onAudioMuteStatusChanged = ({ muted }) => {
|
||||||
|
const action = muted ? ElementWidgetActions.MuteAudio : ElementWidgetActions.UnmuteAudio;
|
||||||
|
widgetApi?.transport.send(action, {});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onVideoMuteStatusChanged = ({ muted }) => {
|
||||||
|
if (muted) {
|
||||||
|
// Jitsi Meet always sends a "video muted" event directly before
|
||||||
|
// hanging up, which we need to ignore by padding the timeout here,
|
||||||
|
// otherwise the React SDK will mistakenly think the user turned off
|
||||||
|
// their video by hand
|
||||||
|
setTimeout(() => {
|
||||||
|
if (meetApi) widgetApi?.transport.send(ElementWidgetActions.MuteVideo, {});
|
||||||
|
}, 200);
|
||||||
|
} else {
|
||||||
|
widgetApi?.transport.send(ElementWidgetActions.UnmuteVideo, {});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateParticipants = () => {
|
||||||
|
widgetApi?.transport.send(ElementWidgetActions.CallParticipants, {
|
||||||
|
participants: meetApi.getParticipantsInfo(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onLog = ({ logLevel, args }) =>
|
||||||
|
(parent as unknown as typeof global).mx_rage_logger?.log(logLevel, ...args);
|
||||||
|
|
Loading…
Reference in a new issue