Skip to content

Commit

Permalink
Connect to Jitsi unmuted by default (#22660)
Browse files Browse the repository at this point in the history
* Connect to Jitsi unmuted by default

* Refactor joinConference to placate SonarQube
  • Loading branch information
robintown authored Jun 27, 2022
1 parent 9eda502 commit 5f176fa
Showing 1 changed file with 79 additions and 67 deletions.
146 changes: 79 additions & 67 deletions src/vector/jitsi/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ const ack = (ev: CustomEvent<IWidgetApiRequest>) => widgetApi.transport.reply(ev
widgetApi.on(`action:${ElementWidgetActions.JoinCall}`,
(ev: CustomEvent<IWidgetApiRequest>) => {
const { audioDevice, videoDevice } = ev.detail.data;
joinConference(audioDevice as string, videoDevice as string);
joinConference(audioDevice as string | null, videoDevice as string | null);
ack(ev);
},
);
Expand Down Expand Up @@ -322,7 +322,11 @@ function closeConference() {
}

// 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;
if (jitsiAuth === JITSI_OPENIDTOKEN_JWT_AUTH) {
if (!openIdToken?.access_token) { // eslint-disable-line camelcase
Expand Down Expand Up @@ -364,8 +368,8 @@ function joinConference(audioDevice?: string, videoDevice?: string) {
configOverwrite: {
subject: roomName,
startAudioOnly,
startWithAudioMuted: audioDevice == null,
startWithVideoMuted: videoDevice == null,
startWithAudioMuted: audioDevice === null,
startWithVideoMuted: videoDevice === null,
// Request some log levels for inclusion in rageshakes
// Ideally we would capture all possible log levels, but this can
// cause Jitsi Meet to try to post various circular data structures
Expand Down Expand Up @@ -393,76 +397,84 @@ function joinConference(audioDevice?: string, videoDevice?: string) {

// fires once when user joins the conference
// (regardless of video on or off)
meetApi.on("videoConferenceJoined", () => {
// 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, {});
}
meetApi.on("videoConferenceJoined", onVideoConferenceJoined);
meetApi.on("videoConferenceLeft", onVideoConferenceLeft);
meetApi.on("readyToClose", closeConference);
meetApi.on("errorOccurred", onErrorOccurred);
meetApi.on("audioMuteStatusChanged", onAudioMuteStatusChanged);
meetApi.on("videoMuteStatusChanged", onVideoMuteStatusChanged);

// Video rooms should start in tile mode
if (isVideoChannel) meetApi.executeCommand("setTileView", true);
["videoConferenceJoined", "participantJoined", "participantLeft"].forEach(event => {
meetApi.on(event, updateParticipants);
});

meetApi.on("videoConferenceLeft", () => {
notifyHangup();
meetApi = null;
});
// Patch logs into rageshakes
meetApi.on("log", onLog);
}

meetApi.on("readyToClose", closeConference);
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);

meetApi.on("errorOccurred", ({ 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();
}
});
if (widgetApi) {
// ignored promise because we don't care if it works
// noinspection JSIgnoredPromiseFromCall
widgetApi.setAlwaysOnScreen(true);
widgetApi.transport.send(ElementWidgetActions.JoinCall, {});
}

meetApi.on("audioMuteStatusChanged", ({ muted }) => {
const action = muted ? ElementWidgetActions.MuteAudio : ElementWidgetActions.UnmuteAudio;
widgetApi?.transport.send(action, {});
});
// Video rooms should start in tile mode
if (isVideoChannel) meetApi.executeCommand("setTileView", true);
};

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, {});
}
});
const onVideoConferenceLeft = () => {
notifyHangup();
meetApi = null;
};

["videoConferenceJoined", "participantJoined", "participantLeft"].forEach(event => {
meetApi.on(event, () => {
widgetApi?.transport.send(ElementWidgetActions.CallParticipants, {
participants: meetApi.getParticipantsInfo(),
});
});
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(),
});
};

// Patch logs into rageshakes
meetApi.on("log", ({ logLevel, args }) =>
(parent as unknown as typeof global).mx_rage_logger?.log(logLevel, ...args),
);
}
const onLog = ({ logLevel, args }) =>
(parent as unknown as typeof global).mx_rage_logger?.log(logLevel, ...args);

0 comments on commit 5f176fa

Please sign in to comment.