mirror of https://github.com/vector-im/riot-web
Stop connecting to a video room if the widget messaging disappears (#8660)
* Stop connecting to a video room if the widget messaging disappears * Clean up more listeners * Clean up even more listenerspull/28217/head
parent
0343548dbe
commit
7edc4b1965
|
@ -136,14 +136,40 @@ export default class VideoChannelStore extends AsyncStoreWithClient<null> {
|
|||
}
|
||||
}
|
||||
|
||||
// Now that we got the messaging, we need a way to ensure that it doesn't get stopped
|
||||
const dontStopMessaging = new Promise<void>((resolve, reject) => {
|
||||
const listener = (uid: string) => {
|
||||
if (uid === jitsiUid) {
|
||||
cleanup();
|
||||
reject(new Error("Messaging stopped"));
|
||||
}
|
||||
};
|
||||
const done = () => {
|
||||
cleanup();
|
||||
resolve();
|
||||
};
|
||||
const cleanup = () => {
|
||||
messagingStore.off(WidgetMessagingStoreEvent.StopMessaging, listener);
|
||||
this.off(VideoChannelEvent.Connect, done);
|
||||
this.off(VideoChannelEvent.Disconnect, done);
|
||||
};
|
||||
|
||||
messagingStore.on(WidgetMessagingStoreEvent.StopMessaging, listener);
|
||||
this.on(VideoChannelEvent.Connect, done);
|
||||
this.on(VideoChannelEvent.Disconnect, done);
|
||||
});
|
||||
|
||||
if (!messagingStore.isWidgetReady(jitsiUid)) {
|
||||
// Wait for the widget to be ready to receive our join event
|
||||
try {
|
||||
await waitForEvent(
|
||||
messagingStore,
|
||||
WidgetMessagingStoreEvent.WidgetReady,
|
||||
(uid: string) => uid === jitsiUid,
|
||||
);
|
||||
await Promise.race([
|
||||
waitForEvent(
|
||||
messagingStore,
|
||||
WidgetMessagingStoreEvent.WidgetReady,
|
||||
(uid: string) => uid === jitsiUid,
|
||||
),
|
||||
dontStopMessaging,
|
||||
]);
|
||||
} catch (e) {
|
||||
throw new Error(`Video channel in room ${roomId} never became ready: ${e}`);
|
||||
}
|
||||
|
@ -178,11 +204,12 @@ export default class VideoChannelStore extends AsyncStoreWithClient<null> {
|
|||
videoDevice: videoDevice?.label,
|
||||
});
|
||||
try {
|
||||
await waitForJoin;
|
||||
await Promise.race([waitForJoin, dontStopMessaging]);
|
||||
} catch (e) {
|
||||
// If it timed out, clean up our advance preparations
|
||||
this.activeChannel = null;
|
||||
this.roomId = null;
|
||||
|
||||
messaging.off(`action:${ElementWidgetActions.CallParticipants}`, this.onParticipants);
|
||||
messaging.off(`action:${ElementWidgetActions.MuteAudio}`, this.onMuteAudio);
|
||||
messaging.off(`action:${ElementWidgetActions.UnmuteAudio}`, this.onUnmuteAudio);
|
||||
|
|
|
@ -25,6 +25,7 @@ import WidgetUtils from "../../utils/WidgetUtils";
|
|||
|
||||
export enum WidgetMessagingStoreEvent {
|
||||
StoreMessaging = "store_messaging",
|
||||
StopMessaging = "stop_messaging",
|
||||
WidgetReady = "widget_ready",
|
||||
}
|
||||
|
||||
|
@ -71,9 +72,7 @@ export class WidgetMessagingStore extends AsyncStoreWithClient<unknown> {
|
|||
}
|
||||
|
||||
public stopMessaging(widget: Widget, roomId: string) {
|
||||
const uid = WidgetUtils.calcWidgetUid(widget.id, roomId);
|
||||
this.widgetMap.remove(uid)?.stop();
|
||||
this.readyWidgets.delete(uid);
|
||||
this.stopMessagingByUid(WidgetUtils.calcWidgetUid(widget.id, roomId));
|
||||
}
|
||||
|
||||
public getMessaging(widget: Widget, roomId: string): ClientWidgetApi {
|
||||
|
@ -86,6 +85,8 @@ export class WidgetMessagingStore extends AsyncStoreWithClient<unknown> {
|
|||
*/
|
||||
public stopMessagingByUid(widgetUid: string) {
|
||||
this.widgetMap.remove(widgetUid)?.stop();
|
||||
this.readyWidgets.delete(widgetUid);
|
||||
this.emit(WidgetMessagingStoreEvent.StopMessaging, widgetUid);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -114,23 +114,26 @@ describe("VideoChannelStore", () => {
|
|||
expect(store.roomId).toBeFalsy();
|
||||
expect(store.connected).toEqual(false);
|
||||
|
||||
store.connect("!1:example.org", null, null);
|
||||
const connectPromise = store.connect("!1:example.org", null, null);
|
||||
await confirmConnect();
|
||||
await expect(connectPromise).resolves.toBeUndefined();
|
||||
expect(store.roomId).toEqual("!1:example.org");
|
||||
expect(store.connected).toEqual(true);
|
||||
|
||||
store.disconnect();
|
||||
const disconnectPromise = store.disconnect();
|
||||
await confirmDisconnect();
|
||||
await expect(disconnectPromise).resolves.toBeUndefined();
|
||||
expect(store.roomId).toBeFalsy();
|
||||
expect(store.connected).toEqual(false);
|
||||
WidgetMessagingStore.instance.stopMessaging(widget, "!1:example.org");
|
||||
});
|
||||
|
||||
it("waits for messaging when connecting", async () => {
|
||||
store.connect("!1:example.org", null, null);
|
||||
const connectPromise = store.connect("!1:example.org", null, null);
|
||||
WidgetMessagingStore.instance.storeMessaging(widget, "!1:example.org", messaging);
|
||||
widgetReady();
|
||||
await confirmConnect();
|
||||
await expect(connectPromise).resolves.toBeUndefined();
|
||||
expect(store.roomId).toEqual("!1:example.org");
|
||||
expect(store.connected).toEqual(true);
|
||||
|
||||
|
@ -138,4 +141,19 @@ describe("VideoChannelStore", () => {
|
|||
await confirmDisconnect();
|
||||
WidgetMessagingStore.instance.stopMessaging(widget, "!1:example.org");
|
||||
});
|
||||
|
||||
it("rejects if the widget's messaging gets stopped mid-connect", async () => {
|
||||
WidgetMessagingStore.instance.storeMessaging(widget, "!1:example.org", messaging);
|
||||
widgetReady();
|
||||
expect(store.roomId).toBeFalsy();
|
||||
expect(store.connected).toEqual(false);
|
||||
|
||||
const connectPromise = store.connect("!1:example.org", null, null);
|
||||
// Wait for the store to contact the widget API, then stop the messaging
|
||||
await messageSent;
|
||||
WidgetMessagingStore.instance.stopMessaging(widget, "!1:example.org");
|
||||
await expect(connectPromise).rejects.toBeDefined();
|
||||
expect(store.roomId).toBeFalsy();
|
||||
expect(store.connected).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue