Firefox, Safari and WebKitGTK have no Capability Delegation, so the host
can't start a share from its call bar: getDisplayMedia needs the click in
this frame. Until now the host clicked EC's hidden footer button through
the DOM, which only works while the frame is same-origin.
With lotusHostControls + lotusFrameScreenshare the fork now shows EC's own
screenshare button (floating bottom-right, footer still hidden), so the
click is native. controls_state reports frameScreenshare so the host hides
its own button. New toWidget io.lotus.set_frame_screenshare { visible }
lets the host hide it while the room's call policy forbids screensharing
(never while a share is live, so it can still be stopped).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
89 lines
3.0 KiB
TypeScript
89 lines
3.0 KiB
TypeScript
/*
|
|
Copyright 2026 Lotus Guild
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
Please see LICENSE in the repository root for full details.
|
|
*/
|
|
|
|
import { describe, expect, it, vi } from "vitest";
|
|
import { act, render, screen } from "@testing-library/react";
|
|
import userEvent from "@testing-library/user-event";
|
|
import { TooltipProvider } from "@vector-im/compound-web";
|
|
import { BehaviorSubject } from "rxjs";
|
|
|
|
import { type CallViewModel } from "../state/CallViewModel/CallViewModel";
|
|
import { LotusFrameScreenshare } from "./LotusFrameScreenshare";
|
|
import {
|
|
lotusFrameScreenshareEnabled,
|
|
lotusFrameScreenshareVisible$,
|
|
parseFrameScreensharePayload,
|
|
} from "./lotusControls";
|
|
|
|
// lotusFlag memoizes the URL params on first read, so set them once here.
|
|
window.history.pushState(
|
|
{},
|
|
"",
|
|
"/?lotusHostControls=1&lotusFrameScreenshare=1",
|
|
);
|
|
|
|
const mockVm = (
|
|
toggle: (() => void) | null,
|
|
sharing = new BehaviorSubject(false),
|
|
): CallViewModel =>
|
|
({
|
|
sharingScreen$: sharing,
|
|
toggleScreenSharing: toggle,
|
|
}) as unknown as CallViewModel;
|
|
|
|
const renderButton = (vm: CallViewModel): void => {
|
|
render(
|
|
<TooltipProvider>
|
|
<LotusFrameScreenshare vm={vm} />
|
|
</TooltipProvider>,
|
|
);
|
|
};
|
|
|
|
describe("LotusFrameScreenshare", () => {
|
|
it("is enabled by lotusHostControls + lotusFrameScreenshare", () => {
|
|
expect(lotusFrameScreenshareEnabled()).toBe(true);
|
|
});
|
|
|
|
it("toggles the share from a click inside the frame", async () => {
|
|
const toggle = vi.fn();
|
|
renderButton(mockVm(toggle));
|
|
await userEvent.click(screen.getByTestId("lotus_frame_screenshare"));
|
|
expect(toggle).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it("follows the sharing state", () => {
|
|
const sharing = new BehaviorSubject(false);
|
|
renderButton(mockVm(vi.fn(), sharing));
|
|
const button = screen.getByTestId("lotus_frame_screenshare");
|
|
expect(button).toHaveAttribute("aria-checked", "false");
|
|
act(() => sharing.next(true));
|
|
expect(button).toHaveAttribute("aria-checked", "true");
|
|
});
|
|
|
|
it("hides while the host's policy forbids sharing, unless a share is live", () => {
|
|
const sharing = new BehaviorSubject(false);
|
|
act(() => lotusFrameScreenshareVisible$.next(false));
|
|
renderButton(mockVm(vi.fn(), sharing));
|
|
expect(screen.queryByTestId("lotus_frame_screenshare")).toBeNull();
|
|
act(() => sharing.next(true));
|
|
expect(screen.getByTestId("lotus_frame_screenshare")).toBeInTheDocument();
|
|
act(() => lotusFrameScreenshareVisible$.next(true));
|
|
});
|
|
|
|
it("parses the set_frame_screenshare payload", () => {
|
|
expect(parseFrameScreensharePayload({ visible: false })).toBe(false);
|
|
expect(parseFrameScreensharePayload({ visible: true })).toBe(true);
|
|
expect(parseFrameScreensharePayload({})).toBeUndefined();
|
|
expect(parseFrameScreensharePayload(null)).toBeUndefined();
|
|
});
|
|
|
|
it("renders nothing when screensharing is unavailable", () => {
|
|
renderButton(mockVm(null));
|
|
expect(screen.queryByTestId("lotus_frame_screenshare")).toBeNull();
|
|
});
|
|
});
|