Voice rooms prototype (#21476)

* Document voice rooms labs flag

Signed-off-by: Robin Townsend <robin@robin.town>

* Add join and mute handlers to Jitsi wrapper

Signed-off-by: Robin Townsend <robin@robin.town>

* Document voice rooms labs flag

Signed-off-by: Robin Townsend <robin@robin.town>

* Mark voice rooms as in development

Signed-off-by: Robin Townsend <robin@robin.town>

* ack at the end of widget event handlers

Signed-off-by: Robin Townsend <robin@robin.town>

* Move acks back before suspend points

Signed-off-by: Robin Townsend <robin@robin.town>
This commit is contained in:
Robin 2022-03-22 18:14:27 -04:00 committed by GitHub
parent 269ec4609a
commit 6103f4a9d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 7 deletions

View file

@ -196,3 +196,7 @@ Threading allows users to branch out a new conversation from the main timeline o
Threads can be access by clicking their summary below the root event on the room timeline. Users can find a comprehensive list of threads by click the icon on the room header button. Threads can be access by clicking their summary below the root event on the room timeline. Users can find a comprehensive list of threads by click the icon on the room header button.
This feature might work in degraded mode if the homeserver a user is connected to does not advertise support for the unstable feature `org.matrix.msc3440` when calling the `/versions` API endpoint. This feature might work in degraded mode if the homeserver a user is connected to does not advertise support for the unstable feature `org.matrix.msc3440` when calling the `/versions` API endpoint.
## Voice & video rooms (`feature_voice_rooms`) [In Development]
Enables support for creating and joining voice & video rooms, which are persistent voice chats that users can jump in and out of.

View file

@ -56,6 +56,8 @@ let widgetApi: WidgetApi;
let meetApi: any; // JitsiMeetExternalAPI let meetApi: any; // JitsiMeetExternalAPI
let skipOurWelcomeScreen = false; let skipOurWelcomeScreen = false;
const ack = (ev: CustomEvent<IWidgetApiRequest>) => widgetApi.transport.reply(ev.detail, {});
(async function() { (async function() {
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
@ -133,7 +135,6 @@ let skipOurWelcomeScreen = false;
if (widgetApi) { if (widgetApi) {
await readyPromise; await readyPromise;
await widgetApi.setAlwaysOnScreen(false); // start off as detachable from the screen
// See https://github.com/matrix-org/prosody-mod-auth-matrix-user-verification // See https://github.com/matrix-org/prosody-mod-auth-matrix-user-verification
if (jitsiAuth === JITSI_OPENIDTOKEN_JWT_AUTH) { if (jitsiAuth === JITSI_OPENIDTOKEN_JWT_AUTH) {
@ -142,12 +143,48 @@ let skipOurWelcomeScreen = false;
logger.log("Got OpenID Connect token"); logger.log("Got OpenID Connect token");
} }
// TODO: register widgetApi listeners for PTT controls (https://github.com/vector-im/element-web/issues/12795) widgetApi.on(`action:${ElementWidgetActions.JoinCall}`,
(ev: CustomEvent<IWidgetApiRequest>) => {
joinConference();
ack(ev);
},
);
widgetApi.on(`action:${ElementWidgetActions.HangupCall}`, widgetApi.on(`action:${ElementWidgetActions.HangupCall}`,
(ev: CustomEvent<IWidgetApiRequest>) => { (ev: CustomEvent<IWidgetApiRequest>) => {
if (meetApi) meetApi.executeCommand('hangup'); meetApi?.executeCommand('hangup');
widgetApi.transport.reply(ev.detail, {}); // ack ack(ev);
},
);
widgetApi.on(`action:${ElementWidgetActions.MuteAudio}`,
async (ev: CustomEvent<IWidgetApiRequest>) => {
ack(ev);
if (meetApi && !await meetApi.isAudioMuted()) {
meetApi.executeCommand('toggleAudio');
}
},
);
widgetApi.on(`action:${ElementWidgetActions.UnmuteAudio}`,
async (ev: CustomEvent<IWidgetApiRequest>) => {
ack(ev);
if (meetApi && await meetApi.isAudioMuted()) {
meetApi.executeCommand('toggleAudio');
}
},
);
widgetApi.on(`action:${ElementWidgetActions.MuteVideo}`,
async (ev: CustomEvent<IWidgetApiRequest>) => {
ack(ev);
if (meetApi && !await meetApi.isVideoMuted()) {
meetApi.executeCommand('toggleVideo');
}
},
);
widgetApi.on(`action:${ElementWidgetActions.UnmuteVideo}`,
async (ev: CustomEvent<IWidgetApiRequest>) => {
ack(ev);
if (meetApi && await meetApi.isVideoMuted()) {
meetApi.executeCommand('toggleVideo');
}
}, },
); );
widgetApi.on(`action:${ElementWidgetActions.StartLiveStream}`, widgetApi.on(`action:${ElementWidgetActions.StartLiveStream}`,
@ -160,7 +197,7 @@ let skipOurWelcomeScreen = false;
//rtmpStreamKey: ev.detail.data.rtmpStreamKey, //rtmpStreamKey: ev.detail.data.rtmpStreamKey,
youtubeStreamKey: ev.detail.data.rtmpStreamKey, youtubeStreamKey: ev.detail.data.rtmpStreamKey,
}); });
widgetApi.transport.reply(ev.detail, {}); // ack ack(ev);
} else { } else {
widgetApi.transport.reply(ev.detail, { error: { message: "Conference not joined" } }); widgetApi.transport.reply(ev.detail, { error: { message: "Conference not joined" } });
} }
@ -293,6 +330,7 @@ function joinConference() { // event handler bound in HTML
// ignored promise because we don't care if it works // ignored promise because we don't care if it works
// noinspection JSIgnoredPromiseFromCall // noinspection JSIgnoredPromiseFromCall
widgetApi.setAlwaysOnScreen(true); widgetApi.setAlwaysOnScreen(true);
widgetApi.transport.send(ElementWidgetActions.JoinCall, {});
} }
}); });
@ -300,9 +338,13 @@ function joinConference() { // event handler bound in HTML
switchVisibleContainers(); switchVisibleContainers();
if (widgetApi) { if (widgetApi) {
// We send the hangup event before setAlwaysOnScreen, because the latter
// can cause the receiving side to instantly stop listening.
// ignored promise because we don't care if it works // ignored promise because we don't care if it works
// noinspection JSIgnoredPromiseFromCall // noinspection JSIgnoredPromiseFromCall
widgetApi.setAlwaysOnScreen(false); widgetApi.transport.send(ElementWidgetActions.HangupCall, {}).then(() =>
widgetApi.setAlwaysOnScreen(false),
);
} }
document.getElementById("jitsiContainer").innerHTML = ""; document.getElementById("jitsiContainer").innerHTML = "";
@ -312,4 +354,22 @@ function joinConference() { // event handler bound in HTML
skipToJitsiSplashScreen(); skipToJitsiSplashScreen();
} }
}); });
meetApi.on("audioMuteStatusChanged", ({ muted }) => {
const action = muted ? ElementWidgetActions.MuteAudio : ElementWidgetActions.UnmuteAudio;
widgetApi.transport.send(action, {});
});
meetApi.on("videoMuteStatusChanged", ({ muted }) => {
const action = muted ? ElementWidgetActions.MuteVideo : ElementWidgetActions.UnmuteVideo;
widgetApi.transport.send(action, {});
});
["videoConferenceJoined", "participantJoined", "participantLeft"].forEach(event => {
meetApi.on(event, () => {
widgetApi?.transport.send(ElementWidgetActions.CallParticipants, {
participants: meetApi.getParticipantsInfo(),
});
});
});
} }