Make video rooms compatible with matrix RTC (#11829)
* Make video rooms compatible with matrix RTC Signed-off-by: Timo K <toger5@hotmail.de> * comment fixes Signed-off-by: Timo K <toger5@hotmail.de> * fix tests by destroying the call. Otherwise create wont recreate for ec. Signed-off-by: Timo K <toger5@hotmail.de> --------- Signed-off-by: Timo K <toger5@hotmail.de>
This commit is contained in:
parent
90419bdffd
commit
224b9171dd
3 changed files with 21 additions and 14 deletions
|
@ -50,6 +50,7 @@ import ActiveWidgetStore, { ActiveWidgetStoreEvent } from "../stores/ActiveWidge
|
||||||
import { getCurrentLanguage } from "../languageHandler";
|
import { getCurrentLanguage } from "../languageHandler";
|
||||||
import { FontWatcher } from "../settings/watchers/FontWatcher";
|
import { FontWatcher } from "../settings/watchers/FontWatcher";
|
||||||
import { PosthogAnalytics } from "../PosthogAnalytics";
|
import { PosthogAnalytics } from "../PosthogAnalytics";
|
||||||
|
import { UPDATE_EVENT } from "../stores/AsyncStore";
|
||||||
|
|
||||||
const TIMEOUT_MS = 16000;
|
const TIMEOUT_MS = 16000;
|
||||||
|
|
||||||
|
@ -225,7 +226,7 @@ export abstract class Call extends TypedEventEmitter<CallEvent, CallEventHandler
|
||||||
const messagingStore = WidgetMessagingStore.instance;
|
const messagingStore = WidgetMessagingStore.instance;
|
||||||
this.messaging = messagingStore.getMessagingForUid(this.widgetUid) ?? null;
|
this.messaging = messagingStore.getMessagingForUid(this.widgetUid) ?? null;
|
||||||
if (!this.messaging) {
|
if (!this.messaging) {
|
||||||
// The widget might still be initializing, so wait for it
|
// The widget might still be initializing, so wait for it.
|
||||||
try {
|
try {
|
||||||
await waitForEvent(
|
await waitForEvent(
|
||||||
messagingStore,
|
messagingStore,
|
||||||
|
@ -632,12 +633,10 @@ export class ElementCall extends Call {
|
||||||
this.emit(CallEvent.Layout, value);
|
this.emit(CallEvent.Layout, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static createCallWidget(roomId: string, client: MatrixClient): IApp {
|
private static createOrGetCallWidget(roomId: string, client: MatrixClient): IApp {
|
||||||
const ecWidget = WidgetStore.instance.getApps(roomId).find((app) => WidgetType.CALL.matches(app.type));
|
const ecWidget = WidgetStore.instance.getApps(roomId).find((app) => WidgetType.CALL.matches(app.type));
|
||||||
if (ecWidget) {
|
if (ecWidget) {
|
||||||
logger.log("There is already a widget in this room, so we recreate it");
|
return ecWidget;
|
||||||
ActiveWidgetStore.instance.destroyPersistentWidget(ecWidget.id, ecWidget.roomId);
|
|
||||||
WidgetStore.instance.removeVirtualWidget(ecWidget.id, ecWidget.roomId);
|
|
||||||
}
|
}
|
||||||
const accountAnalyticsData = client.getAccountData(PosthogAnalytics.ANALYTICS_EVENT_TYPE);
|
const accountAnalyticsData = client.getAccountData(PosthogAnalytics.ANALYTICS_EVENT_TYPE);
|
||||||
// The analyticsID is passed directly to element call (EC) since this codepath is only for EC and no other widget.
|
// The analyticsID is passed directly to element call (EC) since this codepath is only for EC and no other widget.
|
||||||
|
@ -707,7 +706,7 @@ export class ElementCall extends Call {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static get(room: Room): ElementCall | null {
|
public static get(room: Room): ElementCall | null {
|
||||||
// Only supported in the new group call experience or in video rooms
|
// Only supported in the new group call experience or in video rooms.
|
||||||
if (
|
if (
|
||||||
SettingsStore.getValue("feature_group_calls") ||
|
SettingsStore.getValue("feature_group_calls") ||
|
||||||
(SettingsStore.getValue("feature_video_rooms") &&
|
(SettingsStore.getValue("feature_video_rooms") &&
|
||||||
|
@ -715,15 +714,16 @@ export class ElementCall extends Call {
|
||||||
room.isCallRoom())
|
room.isCallRoom())
|
||||||
) {
|
) {
|
||||||
const apps = WidgetStore.instance.getApps(room.roomId);
|
const apps = WidgetStore.instance.getApps(room.roomId);
|
||||||
const ecWidget = apps.find((app) => WidgetType.CALL.matches(app.type));
|
const hasEcWidget = apps.some((app) => WidgetType.CALL.matches(app.type));
|
||||||
const session = room.client.matrixRTC.getRoomSession(room);
|
const session = room.client.matrixRTC.getRoomSession(room);
|
||||||
|
|
||||||
// A call is present if we
|
// A call is present if we
|
||||||
// - have a widget: This means the create function was called
|
// - have a widget: This means the create function was called.
|
||||||
// - or there is a running session where we have not yet created a widget for.
|
// - or there is a running session where we have not yet created a widget for.
|
||||||
if (ecWidget || session.memberships.length !== 0) {
|
// - or this this is a call room. Then we also always want to show a call.
|
||||||
|
if (hasEcWidget || session.memberships.length !== 0 || room.isCallRoom()) {
|
||||||
// create a widget for the case we are joining a running call and don't have on yet.
|
// create a widget for the case we are joining a running call and don't have on yet.
|
||||||
const availableOrCreatedWidget = ecWidget ?? ElementCall.createCallWidget(room.roomId, room.client);
|
const availableOrCreatedWidget = ElementCall.createOrGetCallWidget(room.roomId, room.client);
|
||||||
return new ElementCall(session, availableOrCreatedWidget, room.client);
|
return new ElementCall(session, availableOrCreatedWidget, room.client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -738,7 +738,8 @@ export class ElementCall extends Call {
|
||||||
room.isCallRoom();
|
room.isCallRoom();
|
||||||
|
|
||||||
console.log("Intend is ", isVideoRoom ? "VideoRoom" : "Prompt", " TODO, handle intent appropriately");
|
console.log("Intend is ", isVideoRoom ? "VideoRoom" : "Prompt", " TODO, handle intent appropriately");
|
||||||
ElementCall.createCallWidget(room.roomId, room.client);
|
ElementCall.createOrGetCallWidget(room.roomId, room.client);
|
||||||
|
WidgetStore.instance.emit(UPDATE_EVENT, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async performConnection(
|
protected async performConnection(
|
||||||
|
@ -790,7 +791,8 @@ export class ElementCall extends Call {
|
||||||
}
|
}
|
||||||
|
|
||||||
private onRTCSessionEnded = (roomId: string, session: MatrixRTCSession): void => {
|
private onRTCSessionEnded = (roomId: string, session: MatrixRTCSession): void => {
|
||||||
if (roomId == this.roomId) {
|
// Don't destroy widget on hangup for video call rooms.
|
||||||
|
if (roomId == this.roomId && !this.room.isCallRoom()) {
|
||||||
this.destroy();
|
this.destroy();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -202,7 +202,6 @@ export default class WidgetStore extends AsyncStoreWithClient<IState> {
|
||||||
const app = WidgetUtils.makeAppConfig(widget.id, widget, widget.creatorUserId, roomId, undefined);
|
const app = WidgetUtils.makeAppConfig(widget.id, widget, widget.creatorUserId, roomId, undefined);
|
||||||
this.widgetMap.set(WidgetUtils.getWidgetUid(app), app);
|
this.widgetMap.set(WidgetUtils.getWidgetUid(app), app);
|
||||||
this.roomMap.get(roomId)!.widgets.push(app);
|
this.roomMap.get(roomId)!.widgets.push(app);
|
||||||
this.emit(UPDATE_EVENT, roomId);
|
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -596,16 +596,19 @@ describe("ElementCall", () => {
|
||||||
it("finds calls", async () => {
|
it("finds calls", async () => {
|
||||||
await ElementCall.create(room);
|
await ElementCall.create(room);
|
||||||
expect(Call.get(room)).toBeInstanceOf(ElementCall);
|
expect(Call.get(room)).toBeInstanceOf(ElementCall);
|
||||||
|
Call.get(room)?.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("finds ongoing calls that are created by the session manager", async () => {
|
it("finds ongoing calls that are created by the session manager", async () => {
|
||||||
// There is an existing session created by another user in this room.
|
// There is an existing session created by another user in this room.
|
||||||
client.matrixRTC.getRoomSession.mockReturnValue({
|
client.matrixRTC.getRoomSession.mockReturnValue({
|
||||||
on: (ev: any, fn: any) => {},
|
on: (ev: any, fn: any) => {},
|
||||||
|
off: (ev: any, fn: any) => {},
|
||||||
memberships: [{ fakeVal: "fake membership" }],
|
memberships: [{ fakeVal: "fake membership" }],
|
||||||
} as unknown as MatrixRTCSession);
|
} as unknown as MatrixRTCSession);
|
||||||
const call = Call.get(room);
|
const call = Call.get(room);
|
||||||
if (!(call instanceof ElementCall)) throw new Error("Failed to create call");
|
if (!(call instanceof ElementCall)) throw new Error("Failed to create call");
|
||||||
|
call.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("passes font settings through widget URL", async () => {
|
it("passes font settings through widget URL", async () => {
|
||||||
|
@ -642,6 +645,7 @@ describe("ElementCall", () => {
|
||||||
|
|
||||||
const urlParams1 = new URLSearchParams(new URL(call1.widget.url).hash.slice(1));
|
const urlParams1 = new URLSearchParams(new URL(call1.widget.url).hash.slice(1));
|
||||||
expect(urlParams1.has("allowIceFallback")).toBe(false);
|
expect(urlParams1.has("allowIceFallback")).toBe(false);
|
||||||
|
call1.destroy();
|
||||||
|
|
||||||
// Now test with the preference set to true
|
// Now test with the preference set to true
|
||||||
const originalGetValue = SettingsStore.getValue;
|
const originalGetValue = SettingsStore.getValue;
|
||||||
|
@ -654,13 +658,14 @@ describe("ElementCall", () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
await ElementCall.create(room);
|
ElementCall.create(room);
|
||||||
const call2 = Call.get(room);
|
const call2 = Call.get(room);
|
||||||
if (!(call2 instanceof ElementCall)) throw new Error("Failed to create call");
|
if (!(call2 instanceof ElementCall)) throw new Error("Failed to create call");
|
||||||
|
|
||||||
const urlParams2 = new URLSearchParams(new URL(call2.widget.url).hash.slice(1));
|
const urlParams2 = new URLSearchParams(new URL(call2.widget.url).hash.slice(1));
|
||||||
expect(urlParams2.has("allowIceFallback")).toBe(true);
|
expect(urlParams2.has("allowIceFallback")).toBe(true);
|
||||||
|
|
||||||
|
call2.destroy();
|
||||||
SettingsStore.getValue = originalGetValue;
|
SettingsStore.getValue = originalGetValue;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -677,6 +682,7 @@ describe("ElementCall", () => {
|
||||||
|
|
||||||
const urlParams = new URLSearchParams(new URL(call.widget.url).hash.slice(1));
|
const urlParams = new URLSearchParams(new URL(call.widget.url).hash.slice(1));
|
||||||
expect(urlParams.get("analyticsID")).toBe("123456789987654321");
|
expect(urlParams.get("analyticsID")).toBe("123456789987654321");
|
||||||
|
call.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does not pass analyticsID if `pseudonymousAnalyticsOptIn` set to false", async () => {
|
it("does not pass analyticsID if `pseudonymousAnalyticsOptIn` set to false", async () => {
|
||||||
|
|
Loading…
Reference in a new issue