Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to the new session API for screen-sharing #11266

Merged
merged 2 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ export class ExistingSource extends React.Component<ExistingSourceIProps> {
export interface PickerIState {
selectedTab: Tabs;
sources: Array<DesktopCapturerSource>;
selectedSource: DesktopCapturerSource | null;
selectedSource?: DesktopCapturerSource;
}
export interface PickerIProps {
onFinished(sourceId?: string): void;
onFinished(source?: DesktopCapturerSource): void;
}

type TabId = "screen" | "window";
Expand All @@ -96,7 +96,6 @@ export default class DesktopCapturerSourcePicker extends React.Component<PickerI
this.state = {
selectedTab: Tabs.Screens,
sources: [],
selectedSource: null,
};
}

Expand Down Expand Up @@ -125,11 +124,11 @@ export default class DesktopCapturerSourcePicker extends React.Component<PickerI
};

private onShare = (): void => {
this.props.onFinished(this.state.selectedSource?.id);
this.props.onFinished(this.state.selectedSource);
};

private onTabChange = (): void => {
this.setState({ selectedSource: null });
this.setState({ selectedSource: undefined });
};

private onCloseClick = (): void => {
Expand Down
15 changes: 1 addition & 14 deletions src/components/views/voip/LegacyCallView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,9 @@ import VideoFeed from "./VideoFeed";
import RoomAvatar from "../avatars/RoomAvatar";
import AccessibleButton from "../elements/AccessibleButton";
import { avatarUrlForMember } from "../../../Avatar";
import DesktopCapturerSourcePicker from "../elements/DesktopCapturerSourcePicker";
import Modal from "../../../Modal";
import LegacyCallViewSidebar from "./LegacyCallViewSidebar";
import LegacyCallViewHeader from "./LegacyCallView/LegacyCallViewHeader";
import LegacyCallViewButtons from "./LegacyCallView/LegacyCallViewButtons";
import PlatformPeg from "../../../PlatformPeg";
import { ActionPayload } from "../../../dispatcher/payloads";
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
Expand Down Expand Up @@ -289,17 +286,7 @@ export default class LegacyCallView extends React.Component<IProps, IState> {
if (this.state.screensharing) {
isScreensharing = await this.props.call.setScreensharingEnabled(false);
} else {
if (PlatformPeg.get()?.supportsDesktopCapturer()) {
const { finished } = Modal.createDialog(DesktopCapturerSourcePicker);
const [source] = await finished;
if (!source) return;

isScreensharing = await this.props.call.setScreensharingEnabled(true, {
desktopCapturerSourceId: source,
});
} else {
isScreensharing = await this.props.call.setScreensharingEnabled(true);
}
isScreensharing = await this.props.call.setScreensharingEnabled(true);
}

this.setState({
Expand Down
26 changes: 0 additions & 26 deletions src/models/Call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,7 @@ import { ElementWidgetActions } from "../stores/widgets/ElementWidgetActions";
import WidgetStore from "../stores/WidgetStore";
import { WidgetMessagingStore, WidgetMessagingStoreEvent } from "../stores/widgets/WidgetMessagingStore";
import ActiveWidgetStore, { ActiveWidgetStoreEvent } from "../stores/ActiveWidgetStore";
import PlatformPeg from "../PlatformPeg";
import { getCurrentLanguage } from "../languageHandler";
import DesktopCapturerSourcePicker from "../components/views/elements/DesktopCapturerSourcePicker";
import Modal from "../Modal";
import { FontWatcher } from "../settings/watchers/FontWatcher";
import { PosthogAnalytics } from "../PosthogAnalytics";

Expand Down Expand Up @@ -762,7 +759,6 @@ export class ElementCall extends Call {
this.messaging!.on(`action:${ElementWidgetActions.HangupCall}`, this.onHangup);
this.messaging!.on(`action:${ElementWidgetActions.TileLayout}`, this.onTileLayout);
this.messaging!.on(`action:${ElementWidgetActions.SpotlightLayout}`, this.onSpotlightLayout);
this.messaging!.on(`action:${ElementWidgetActions.ScreenshareRequest}`, this.onScreenshareRequest);
}

protected async performDisconnection(): Promise<void> {
Expand All @@ -777,7 +773,6 @@ export class ElementCall extends Call {
this.messaging!.off(`action:${ElementWidgetActions.HangupCall}`, this.onHangup);
this.messaging!.off(`action:${ElementWidgetActions.TileLayout}`, this.onTileLayout);
this.messaging!.off(`action:${ElementWidgetActions.SpotlightLayout}`, this.onSpotlightLayout);
this.messaging!.off(`action:${ElementWidgetActions.ScreenshareRequest}`, this.onScreenshareRequest);
super.setDisconnected();
this.groupCall.enteredViaAnotherSession = false;
}
Expand Down Expand Up @@ -878,25 +873,4 @@ export class ElementCall extends Call {
this.layout = Layout.Spotlight;
await this.messaging!.transport.reply(ev.detail, {}); // ack
};

private onScreenshareRequest = async (ev: CustomEvent<IWidgetApiRequest>): Promise<void> => {
ev.preventDefault();

if (PlatformPeg.get()?.supportsDesktopCapturer()) {
await this.messaging!.transport.reply(ev.detail, { pending: true });

const { finished } = Modal.createDialog(DesktopCapturerSourcePicker);
const [source] = await finished;

if (source) {
await this.messaging!.transport.send(ElementWidgetActions.ScreenshareStart, {
desktopCapturerSourceId: source,
});
} else {
await this.messaging!.transport.send(ElementWidgetActions.ScreenshareStop, {});
}
} else {
await this.messaging!.transport.reply(ev.detail, { pending: false });
}
};
}
13 changes: 0 additions & 13 deletions src/stores/widgets/ElementWidgetActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,6 @@ export enum ElementWidgetActions {
UnmuteVideo = "io.element.unmute_video",
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
TileLayout = "io.element.tile_layout",
SpotlightLayout = "io.element.spotlight_layout",
Expand Down
79 changes: 0 additions & 79 deletions test/models/Call-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ import { WidgetMessagingStore } from "../../src/stores/widgets/WidgetMessagingSt
import ActiveWidgetStore, { ActiveWidgetStoreEvent } from "../../src/stores/ActiveWidgetStore";
import { ElementWidgetActions } from "../../src/stores/widgets/ElementWidgetActions";
import SettingsStore from "../../src/settings/SettingsStore";
import Modal, { IHandle } from "../../src/Modal";
import PlatformPeg from "../../src/PlatformPeg";
import { PosthogAnalytics } from "../../src/PosthogAnalytics";

jest.spyOn(MediaDeviceHandler, "getDevices").mockResolvedValue({
Expand Down Expand Up @@ -947,83 +945,6 @@ describe("ElementCall", () => {
call.off(CallEvent.Layout, onLayout);
});

describe("screensharing", () => {
it("passes source id if we can get it", async () => {
const sourceId = "source_id";
jest.spyOn(Modal, "createDialog").mockReturnValue({
finished: new Promise((r) => r([sourceId])),
} as IHandle<any>);
jest.spyOn(PlatformPeg.get()!, "supportsDesktopCapturer").mockReturnValue(true);

await call.connect();

messaging.emit(
`action:${ElementWidgetActions.ScreenshareRequest}`,
new CustomEvent("widgetapirequest", { detail: {} }),
);

await waitFor(() => {
expect(messaging!.transport.reply).toHaveBeenCalledWith(
expect.objectContaining({}),
expect.objectContaining({ pending: true }),
);
});

await waitFor(() => {
expect(messaging!.transport.send).toHaveBeenCalledWith(
"io.element.screenshare_start",
expect.objectContaining({ desktopCapturerSourceId: sourceId }),
);
});
});

it("sends ScreenshareStop if we couldn't get a source id", async () => {
jest.spyOn(Modal, "createDialog").mockReturnValue({
finished: new Promise((r) => r([null])),
} as IHandle<any>);
jest.spyOn(PlatformPeg.get()!, "supportsDesktopCapturer").mockReturnValue(true);

await call.connect();

messaging.emit(
`action:${ElementWidgetActions.ScreenshareRequest}`,
new CustomEvent("widgetapirequest", { detail: {} }),
);

await waitFor(() => {
expect(messaging!.transport.reply).toHaveBeenCalledWith(
expect.objectContaining({}),
expect.objectContaining({ pending: true }),
);
});

await waitFor(() => {
expect(messaging!.transport.send).toHaveBeenCalledWith(
"io.element.screenshare_stop",
expect.objectContaining({}),
);
});
});

it("replies with pending: false if we don't support desktop capturer", async () => {
jest.spyOn(PlatformPeg.get()!, "supportsDesktopCapturer").mockReturnValue(false);

await call.connect();

messaging.emit(
`action:${ElementWidgetActions.ScreenshareRequest}`,
new CustomEvent("widgetapirequest", { detail: {} }),
);

await waitFor(() => {
expect(messaging!.transport.reply).toHaveBeenCalledWith(
expect.objectContaining({}),
expect.objectContaining({ pending: false }),
);
});
});
});

it("ends the call immediately if we're the last participant to leave", async () => {
await call.connect();
const onDestroy = jest.fn();
Expand Down