Fix embedded Element Call screen sharing (#9485)
* Fix embedded Element Call screen sharing Makes it a request in each direction rather than a request and reply since replies to requests time out and so can't wait for user interaction. * Fix tests
This commit is contained in:
parent
e4c44dc282
commit
37e613bb05
3 changed files with 50 additions and 20 deletions
|
@ -816,7 +816,7 @@ export class ElementCall extends Call {
|
||||||
this.messaging!.on(`action:${ElementWidgetActions.HangupCall}`, this.onHangup);
|
this.messaging!.on(`action:${ElementWidgetActions.HangupCall}`, this.onHangup);
|
||||||
this.messaging!.on(`action:${ElementWidgetActions.TileLayout}`, this.onTileLayout);
|
this.messaging!.on(`action:${ElementWidgetActions.TileLayout}`, this.onTileLayout);
|
||||||
this.messaging!.on(`action:${ElementWidgetActions.SpotlightLayout}`, this.onSpotlightLayout);
|
this.messaging!.on(`action:${ElementWidgetActions.SpotlightLayout}`, this.onSpotlightLayout);
|
||||||
this.messaging!.on(`action:${ElementWidgetActions.Screenshare}`, this.onScreenshare);
|
this.messaging!.on(`action:${ElementWidgetActions.ScreenshareRequest}`, this.onScreenshareRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async performDisconnection(): Promise<void> {
|
protected async performDisconnection(): Promise<void> {
|
||||||
|
@ -832,7 +832,7 @@ export class ElementCall extends Call {
|
||||||
this.messaging!.off(`action:${ElementWidgetActions.HangupCall}`, this.onHangup);
|
this.messaging!.off(`action:${ElementWidgetActions.HangupCall}`, this.onHangup);
|
||||||
this.messaging!.off(`action:${ElementWidgetActions.TileLayout}`, this.onTileLayout);
|
this.messaging!.off(`action:${ElementWidgetActions.TileLayout}`, this.onTileLayout);
|
||||||
this.messaging!.off(`action:${ElementWidgetActions.SpotlightLayout}`, this.onSpotlightLayout);
|
this.messaging!.off(`action:${ElementWidgetActions.SpotlightLayout}`, this.onSpotlightLayout);
|
||||||
this.messaging!.off(`action:${ElementWidgetActions.Screenshare}`, this.onSpotlightLayout);
|
this.messaging!.off(`action:${ElementWidgetActions.ScreenshareRequest}`, this.onScreenshareRequest);
|
||||||
super.setDisconnected();
|
super.setDisconnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -952,19 +952,24 @@ export class ElementCall extends Call {
|
||||||
await this.messaging!.transport.reply(ev.detail, {}); // ack
|
await this.messaging!.transport.reply(ev.detail, {}); // ack
|
||||||
};
|
};
|
||||||
|
|
||||||
private onScreenshare = async (ev: CustomEvent<IWidgetApiRequest>) => {
|
private onScreenshareRequest = async (ev: CustomEvent<IWidgetApiRequest>) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
if (PlatformPeg.get().supportsDesktopCapturer()) {
|
if (PlatformPeg.get().supportsDesktopCapturer()) {
|
||||||
|
await this.messaging!.transport.reply(ev.detail, { pending: true });
|
||||||
|
|
||||||
const { finished } = Modal.createDialog(DesktopCapturerSourcePicker);
|
const { finished } = Modal.createDialog(DesktopCapturerSourcePicker);
|
||||||
const [source] = await finished;
|
const [source] = await finished;
|
||||||
|
|
||||||
await this.messaging!.transport.reply(ev.detail, {
|
if (source) {
|
||||||
failed: !source,
|
await this.messaging!.transport.send(ElementWidgetActions.ScreenshareStart, {
|
||||||
desktopCapturerSourceId: source,
|
desktopCapturerSourceId: source,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
await this.messaging!.transport.send(ElementWidgetActions.ScreenshareStop, {});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
await this.messaging!.transport.reply(ev.detail, {});
|
await this.messaging!.transport.reply(ev.detail, { pending: false });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,10 +26,23 @@ export enum ElementWidgetActions {
|
||||||
MuteVideo = "io.element.mute_video",
|
MuteVideo = "io.element.mute_video",
|
||||||
UnmuteVideo = "io.element.unmute_video",
|
UnmuteVideo = "io.element.unmute_video",
|
||||||
StartLiveStream = "im.vector.start_live_stream",
|
StartLiveStream = "im.vector.start_live_stream",
|
||||||
|
|
||||||
|
// Element Call -> host requesting to start a screenshare
|
||||||
|
// (ie. expects a ScreenshareStart once the user has picked a source)
|
||||||
|
// replies with { pending } where pending is true if the host has asked
|
||||||
|
// the user to choose a window and false if not (ie. if the host isn't
|
||||||
|
// running within Electron)
|
||||||
|
ScreenshareRequest = "io.element.screenshare_request",
|
||||||
|
// host -> Element Call telling EC to start screen sharing with
|
||||||
|
// the given source
|
||||||
|
ScreenshareStart = "io.element.screenshare_start",
|
||||||
|
// host -> Element Call telling EC to stop screen sharing, or that
|
||||||
|
// the user cancelled when selecting a source after a ScreenshareRequest
|
||||||
|
ScreenshareStop = "io.element.screenshare_stop",
|
||||||
|
|
||||||
// Actions for switching layouts
|
// Actions for switching layouts
|
||||||
TileLayout = "io.element.tile_layout",
|
TileLayout = "io.element.tile_layout",
|
||||||
SpotlightLayout = "io.element.spotlight_layout",
|
SpotlightLayout = "io.element.spotlight_layout",
|
||||||
Screenshare = "io.element.screenshare",
|
|
||||||
|
|
||||||
OpenIntegrationManager = "integration_manager_open",
|
OpenIntegrationManager = "integration_manager_open",
|
||||||
|
|
||||||
|
|
|
@ -820,19 +820,25 @@ describe("ElementCall", () => {
|
||||||
await call.connect();
|
await call.connect();
|
||||||
|
|
||||||
messaging.emit(
|
messaging.emit(
|
||||||
`action:${ElementWidgetActions.Screenshare}`,
|
`action:${ElementWidgetActions.ScreenshareRequest}`,
|
||||||
new CustomEvent("widgetapirequest", { detail: {} }),
|
new CustomEvent("widgetapirequest", { detail: {} }),
|
||||||
);
|
);
|
||||||
|
|
||||||
waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(messaging!.transport.reply).toHaveBeenCalledWith(
|
expect(messaging!.transport.reply).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({}),
|
expect.objectContaining({}),
|
||||||
expect.objectContaining({ desktopCapturerSourceId: sourceId }),
|
expect.objectContaining({ pending: true }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(messaging!.transport.send).toHaveBeenCalledWith(
|
||||||
|
"io.element.screenshare_start", expect.objectContaining({ desktopCapturerSourceId: sourceId }),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("passes failed if we couldn't get a source id", async () => {
|
it("sends ScreenshareStop if we couldn't get a source id", async () => {
|
||||||
jest.spyOn(Modal, "createDialog").mockReturnValue(
|
jest.spyOn(Modal, "createDialog").mockReturnValue(
|
||||||
{ finished: new Promise((r) => r([null])) } as IHandle<any[]>,
|
{ finished: new Promise((r) => r([null])) } as IHandle<any[]>,
|
||||||
);
|
);
|
||||||
|
@ -841,32 +847,38 @@ describe("ElementCall", () => {
|
||||||
await call.connect();
|
await call.connect();
|
||||||
|
|
||||||
messaging.emit(
|
messaging.emit(
|
||||||
`action:${ElementWidgetActions.Screenshare}`,
|
`action:${ElementWidgetActions.ScreenshareRequest}`,
|
||||||
new CustomEvent("widgetapirequest", { detail: {} }),
|
new CustomEvent("widgetapirequest", { detail: {} }),
|
||||||
);
|
);
|
||||||
|
|
||||||
waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(messaging!.transport.reply).toHaveBeenCalledWith(
|
expect(messaging!.transport.reply).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({}),
|
expect.objectContaining({}),
|
||||||
expect.objectContaining({ failed: true }),
|
expect.objectContaining({ pending: true }),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(messaging!.transport.send).toHaveBeenCalledWith(
|
||||||
|
"io.element.screenshare_stop", expect.objectContaining({ }),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("passes an empty object if we don't support desktop capturer", async () => {
|
it("replies with pending: false if we don't support desktop capturer", async () => {
|
||||||
jest.spyOn(PlatformPeg.get(), "supportsDesktopCapturer").mockReturnValue(false);
|
jest.spyOn(PlatformPeg.get(), "supportsDesktopCapturer").mockReturnValue(false);
|
||||||
|
|
||||||
await call.connect();
|
await call.connect();
|
||||||
|
|
||||||
messaging.emit(
|
messaging.emit(
|
||||||
`action:${ElementWidgetActions.Screenshare}`,
|
`action:${ElementWidgetActions.ScreenshareRequest}`,
|
||||||
new CustomEvent("widgetapirequest", { detail: {} }),
|
new CustomEvent("widgetapirequest", { detail: {} }),
|
||||||
);
|
);
|
||||||
|
|
||||||
waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(messaging!.transport.reply).toHaveBeenCalledWith(
|
expect(messaging!.transport.reply).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({}),
|
expect.objectContaining({}),
|
||||||
expect.objectContaining({}),
|
expect.objectContaining({ pending: false }),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue