Fix screen sharing
* Make the embedded mode screen sharing a request-each-way rather than request-and-reply, since replies time out and so can't wait for the user. * Try normal screen sharing first, then fall back to using the widget API if it fails (for lack of a good way of detecting when we should be using the widget API). Fixes https://github.com/vector-im/element-call/issues/649
This commit is contained in:
@@ -27,10 +27,11 @@ import { MatrixCall } from "matrix-js-sdk/src/webrtc/call";
|
||||
import { CallFeed } from "matrix-js-sdk/src/webrtc/callFeed";
|
||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { IWidgetApiRequest } from "matrix-widget-api";
|
||||
|
||||
import { usePageUnload } from "./usePageUnload";
|
||||
import { TranslatedError, translatedError } from "../TranslatedError";
|
||||
import { ElementWidgetActions, widget } from "../widget";
|
||||
import { ElementWidgetActions, ScreenshareStartData, widget } from "../widget";
|
||||
|
||||
export interface UseGroupCallReturnType {
|
||||
state: GroupCallState;
|
||||
@@ -302,36 +303,82 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallReturnType {
|
||||
groupCall.setMicrophoneMuted(!groupCall.isMicrophoneMuted());
|
||||
}, [groupCall]);
|
||||
|
||||
const toggleScreensharing = useCallback(() => {
|
||||
updateState({ requestingScreenshare: true });
|
||||
const toggleScreensharing = useCallback(async () => {
|
||||
if (!groupCall.isScreensharing()) {
|
||||
// toggling on
|
||||
updateState({ requestingScreenshare: true });
|
||||
|
||||
if (groupCall.isScreensharing()) {
|
||||
groupCall.setScreensharingEnabled(false).then(() => {
|
||||
try {
|
||||
await groupCall.setScreensharingEnabled(true, {
|
||||
audio: true,
|
||||
throwOnFail: true,
|
||||
});
|
||||
updateState({ requestingScreenshare: false });
|
||||
});
|
||||
} else {
|
||||
widget.api.transport
|
||||
.send(ElementWidgetActions.Screenshare, {})
|
||||
.then(
|
||||
(reply: { desktopCapturerSourceId: string; failed?: boolean }) => {
|
||||
if (reply.failed) {
|
||||
updateState({ requestingScreenshare: false });
|
||||
return;
|
||||
}
|
||||
|
||||
groupCall
|
||||
.setScreensharingEnabled(true, {
|
||||
audio: !reply.desktopCapturerSourceId,
|
||||
desktopCapturerSourceId: reply.desktopCapturerSourceId,
|
||||
})
|
||||
.then(() => {
|
||||
updateState({ requestingScreenshare: false });
|
||||
});
|
||||
} catch (e) {
|
||||
// this will fail in Electron because getDisplayMedia just throws a permission
|
||||
// error, so if we have a widget API, try requesting via that.
|
||||
if (widget) {
|
||||
const reply = await widget.api.transport.send(
|
||||
ElementWidgetActions.ScreenshareRequest,
|
||||
{}
|
||||
);
|
||||
if (!reply.pending) {
|
||||
updateState({ requestingScreenshare: false });
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// toggling off
|
||||
groupCall.setScreensharingEnabled(false);
|
||||
}
|
||||
}, [groupCall]);
|
||||
|
||||
const onScreenshareStart = useCallback(
|
||||
async (ev: CustomEvent<IWidgetApiRequest>) => {
|
||||
updateState({ requestingScreenshare: false });
|
||||
await groupCall.setScreensharingEnabled(true, {
|
||||
desktopCapturerSourceId: ev.detail.data
|
||||
.desktopCapturerSourceId as string,
|
||||
audio: !ev.detail.data.desktopCapturerSourceId,
|
||||
});
|
||||
await widget.api.transport.reply(ev.detail, {});
|
||||
},
|
||||
[groupCall]
|
||||
);
|
||||
|
||||
const onScreenshareStop = useCallback(
|
||||
async (ev: CustomEvent<IWidgetApiRequest>) => {
|
||||
updateState({ requestingScreenshare: false });
|
||||
await groupCall.setScreensharingEnabled(false);
|
||||
await widget.api.transport.reply(ev.detail, {});
|
||||
},
|
||||
[groupCall]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (widget) {
|
||||
widget.lazyActions.on(
|
||||
ElementWidgetActions.ScreenshareStart,
|
||||
onScreenshareStart
|
||||
);
|
||||
widget.lazyActions.on(
|
||||
ElementWidgetActions.ScreenshareStop,
|
||||
onScreenshareStop
|
||||
);
|
||||
|
||||
return () => {
|
||||
widget.lazyActions.off(
|
||||
ElementWidgetActions.ScreenshareStart,
|
||||
onScreenshareStart
|
||||
);
|
||||
widget.lazyActions.off(
|
||||
ElementWidgetActions.ScreenshareStop,
|
||||
onScreenshareStop
|
||||
);
|
||||
};
|
||||
}
|
||||
}, [onScreenshareStart, onScreenshareStop]);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user