Voice rooms prototype (#8084)
* Add voice room labs flag Signed-off-by: Robin Townsend <robin@robin.town> * Add more widget actions for interacting with Jitsi Signed-off-by: Robin Townsend <robin@robin.town> * Factor out a more generic Jitsi creation utility Signed-off-by: Robin Townsend <robin@robin.town> * Add utilities for managing voice channels Signed-off-by: Robin Townsend <robin@robin.town> * Enable creation of voice rooms Signed-off-by: Robin Townsend <robin@robin.town> * Force a maximized view of voice channel widgets Signed-off-by: Robin Townsend <robin@robin.town> * Add voice channel store Signed-off-by: Robin Townsend <robin@robin.town> * Factor out a more generic FacePile Signed-off-by: Robin Townsend <robin@robin.town> * Implement room tile changes for voice rooms Signed-off-by: Robin Townsend <robin@robin.town> * Add interactive radio component to the left panel Signed-off-by: Robin Townsend <robin@robin.town> * Test voice rooms Signed-off-by: Robin Townsend <robin@robin.town> * Update name of call room type Signed-off-by: Robin Townsend <robin@robin.town> * Clarify that voice rooms are under development Signed-off-by: Robin Townsend <robin@robin.town> * Use readonly Signed-off-by: Robin Townsend <robin@robin.town> * Move acks to the end of handlers Signed-off-by: Robin Townsend <robin@robin.town> * Add comment about avatar URLs coming from Jitsi Signed-off-by: Robin Townsend <robin@robin.town> * Don't use unicode ellipses for translation reasons? Signed-off-by: Robin Townsend <robin@robin.town> * Fix tests Signed-off-by: Robin Townsend <robin@robin.town> * Fix tests, again Signed-off-by: Robin Townsend <robin@robin.town> * Remove unnecessary export Signed-off-by: Robin Townsend <robin@robin.town> * Ack Jitsi events when we wait for them Signed-off-by: Robin Townsend <robin@robin.town>
This commit is contained in:
parent
f416a970ca
commit
cfabcdda35
32 changed files with 1302 additions and 238 deletions
32
src/utils/VoiceChannelUtils.ts
Normal file
32
src/utils/VoiceChannelUtils.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { CallType } from "matrix-js-sdk/src/webrtc/call";
|
||||
|
||||
import WidgetStore, { IApp } from "../stores/WidgetStore";
|
||||
import { WidgetType } from "../widgets/WidgetType";
|
||||
import WidgetUtils from "./WidgetUtils";
|
||||
|
||||
export const VOICE_CHANNEL_ID = "io.element.voice";
|
||||
|
||||
export const getVoiceChannel = (roomId: string): IApp => {
|
||||
const apps = WidgetStore.instance.getApps(roomId);
|
||||
return apps.find(app => WidgetType.JITSI.matches(app.type) && app.id === VOICE_CHANNEL_ID);
|
||||
};
|
||||
|
||||
export const addVoiceChannel = async (roomId: string, roomName: string) => {
|
||||
await WidgetUtils.addJitsiWidget(roomId, CallType.Voice, "Voice channel", VOICE_CHANNEL_ID, roomName);
|
||||
};
|
|
@ -16,11 +16,14 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import * as url from "url";
|
||||
import { base32 } from "rfc4648";
|
||||
import { Capability, IWidget, IWidgetData, MatrixCapabilities } from "matrix-widget-api";
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { ClientEvent, RoomStateEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { CallType } from "matrix-js-sdk/src/webrtc/call";
|
||||
import { randomLowercaseString, randomUppercaseString } from "matrix-js-sdk/src/randomstring";
|
||||
|
||||
import { MatrixClientPeg } from '../MatrixClientPeg';
|
||||
import SdkConfig from "../SdkConfig";
|
||||
|
@ -29,6 +32,7 @@ import WidgetEchoStore from '../stores/WidgetEchoStore';
|
|||
import SettingsStore from "../settings/SettingsStore";
|
||||
import { IntegrationManagers } from "../integrations/IntegrationManagers";
|
||||
import { WidgetType } from "../widgets/WidgetType";
|
||||
import { Jitsi } from "../widgets/Jitsi";
|
||||
import { objectClone } from "./objects";
|
||||
import { _t } from "../languageHandler";
|
||||
import { IApp } from "../stores/WidgetStore";
|
||||
|
@ -434,6 +438,42 @@ export default class WidgetUtils {
|
|||
await client.setAccountData('m.widgets', userWidgets);
|
||||
}
|
||||
|
||||
static async addJitsiWidget(
|
||||
roomId: string,
|
||||
type: CallType,
|
||||
name: string,
|
||||
widgetId: string,
|
||||
oobRoomName?: string,
|
||||
): Promise<void> {
|
||||
const domain = Jitsi.getInstance().preferredDomain;
|
||||
const auth = await Jitsi.getInstance().getJitsiAuth();
|
||||
|
||||
let confId;
|
||||
if (auth === 'openidtoken-jwt') {
|
||||
// Create conference ID from room ID
|
||||
// For compatibility with Jitsi, use base32 without padding.
|
||||
// More details here:
|
||||
// https://github.com/matrix-org/prosody-mod-auth-matrix-user-verification
|
||||
confId = base32.stringify(Buffer.from(roomId), { pad: false });
|
||||
} else {
|
||||
// Create a random conference ID
|
||||
confId = `Jitsi${randomUppercaseString(1)}${randomLowercaseString(23)}`;
|
||||
}
|
||||
|
||||
// TODO: Remove URL hacks when the mobile clients eventually support v2 widgets
|
||||
const widgetUrl = new URL(WidgetUtils.getLocalJitsiWrapperUrl({ auth }));
|
||||
widgetUrl.search = ''; // Causes the URL class use searchParams instead
|
||||
widgetUrl.searchParams.set('confId', confId);
|
||||
|
||||
await WidgetUtils.setRoomWidget(roomId, widgetId, WidgetType.JITSI, widgetUrl.toString(), name, {
|
||||
conferenceId: confId,
|
||||
roomName: oobRoomName ?? MatrixClientPeg.get().getRoom(roomId)?.name,
|
||||
isAudioOnly: type === CallType.Voice,
|
||||
domain,
|
||||
auth,
|
||||
});
|
||||
}
|
||||
|
||||
static makeAppConfig(
|
||||
appId: string,
|
||||
app: Partial<IApp>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue