mirror of
https://github.com/vector-im/element-call.git
synced 2026-10-13 23:35:51 +00:00
scaling based on component size instead webview size
This commit is contained in:
@@ -14,7 +14,7 @@ import {
|
||||
type MockedFunction,
|
||||
vi,
|
||||
} from "vitest";
|
||||
import { render, type RenderResult } from "@testing-library/react";
|
||||
import { act, render, type RenderResult } from "@testing-library/react";
|
||||
import { type LocalParticipant } from "livekit-client";
|
||||
import { BehaviorSubject, of } from "rxjs";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
@@ -51,6 +51,7 @@ import { AppBar } from "../AppBar";
|
||||
import { type MatrixInfo } from "./VideoPreview";
|
||||
import { ProcessorProvider } from "../livekit/TrackProcessorContext";
|
||||
import { initializeWidget } from "../widget";
|
||||
import { RootElementProvider } from "../RootElementContext";
|
||||
|
||||
initializeWidget();
|
||||
vi.hoisted(
|
||||
@@ -263,4 +264,71 @@ describe("ActiveCall", () => {
|
||||
// Rendering at all proves ActiveCall created all of its view models
|
||||
expect(await findByTestId("incall_leave")).toBeVisible();
|
||||
});
|
||||
|
||||
it("lays the call out for the size of its root element", async () => {
|
||||
// jsdom has no layout and no ResizeObserver: the root reports whatever
|
||||
// size we say, and the observer notifies whenever we tell it to
|
||||
let size = { width: 1000, height: 800 };
|
||||
const root = document.createElement("div");
|
||||
Object.defineProperty(root, "clientWidth", { get: () => size.width });
|
||||
Object.defineProperty(root, "clientHeight", { get: () => size.height });
|
||||
document.body.appendChild(root);
|
||||
|
||||
const observers: (() => void)[] = [];
|
||||
const originalResizeObserver = window.ResizeObserver;
|
||||
window.ResizeObserver = class {
|
||||
public constructor(private readonly callback: ResizeObserverCallback) {}
|
||||
public observe(): void {
|
||||
observers.push(() => this.callback([], this as ResizeObserver));
|
||||
}
|
||||
public unobserve(): void {}
|
||||
public disconnect(): void {}
|
||||
} as unknown as typeof ResizeObserver;
|
||||
|
||||
try {
|
||||
const mediaDevices = mockMediaDevices({});
|
||||
const { rtcSession, matrixRoom } = getBasicRTCSession([local, alice]);
|
||||
const { findByTestId, container } = render(
|
||||
<BrowserRouter>
|
||||
<RootElementProvider value={root}>
|
||||
<MediaDevicesContext value={mediaDevices}>
|
||||
<ProcessorProvider>
|
||||
<TooltipProvider>
|
||||
<RoomContext value={mockLivekitRoom({ localParticipant })}>
|
||||
<ActiveCall
|
||||
client={matrixRoom.client}
|
||||
rtcSession={rtcSession.asMockedSession()}
|
||||
matrixRoom={matrixRoom}
|
||||
muteStates={mockMuteStates()}
|
||||
matrixInfo={matrixInfo}
|
||||
onShareClick={null}
|
||||
e2eeSystem={{ kind: E2eeType.NONE }}
|
||||
onLeft={(): void => {}}
|
||||
/>
|
||||
</RoomContext>
|
||||
</TooltipProvider>
|
||||
</ProcessorProvider>
|
||||
</MediaDevicesContext>
|
||||
</RootElementProvider>
|
||||
</BrowserRouter>,
|
||||
{ container: root },
|
||||
);
|
||||
await findByTestId("incall_leave");
|
||||
const call = container.querySelector("[data-layout]")!;
|
||||
expect(call.getAttribute("data-layout")).not.toBe("pip");
|
||||
|
||||
// The host shrinks the container to a corner of its page. The window has
|
||||
// not changed at all — what matters is the element we were given.
|
||||
size = { width: 300, height: 300 };
|
||||
act(() => observers.forEach((notify) => notify()));
|
||||
expect(call.getAttribute("data-layout")).toBe("pip");
|
||||
|
||||
size = { width: 1000, height: 800 };
|
||||
act(() => observers.forEach((notify) => notify()));
|
||||
expect(call.getAttribute("data-layout")).not.toBe("pip");
|
||||
} finally {
|
||||
window.ResizeObserver = originalResizeObserver;
|
||||
root.remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,6 +29,8 @@ import { Header, LeftNav, RightNav, RoomHeaderInfo } from "../Header";
|
||||
import { HeaderStyle, useUrlParams } from "../UrlParams";
|
||||
import { useCallViewKeyboardShortcuts } from "../useCallViewKeyboardShortcuts";
|
||||
import { useHostBridge } from "../HostBridge.ts";
|
||||
import { useRootElement } from "../RootElementContext";
|
||||
import { observeElementSize$ } from "../utils/elementSize";
|
||||
import styles from "./InCallView.module.css";
|
||||
import { GridTile } from "../tile/GridTile";
|
||||
import { SettingsModal, defaultSettingsTab } from "../settings/SettingsModal";
|
||||
@@ -120,6 +122,9 @@ export const ActiveCall: FC<ActiveCallProps> = (props) => {
|
||||
const hostBridge = useHostBridge();
|
||||
const mediaDevices = useMediaDevices();
|
||||
const trackProcessorState$ = useTrackProcessorObservable$();
|
||||
// The element we have to draw the call in: the page, or the container a host
|
||||
// gave us. Its size, not the window's, decides how the call is laid out.
|
||||
const rootElement = useRootElement();
|
||||
useEffect(() => {
|
||||
rootLogger.info("START CALL VIEW SCOPE");
|
||||
const scope = new ObservableScope();
|
||||
@@ -140,6 +145,7 @@ export const ActiveCall: FC<ActiveCallProps> = (props) => {
|
||||
autoLeaveWhenOthersLeft,
|
||||
waitForCallPickup: waitForCallPickup && sendNotificationType === "ring",
|
||||
matrixRTCMode$: matrixRTCModeSetting.value$,
|
||||
windowSize$: scope.behavior(observeElementSize$(rootElement)),
|
||||
},
|
||||
reactionsReader.raisedHands$,
|
||||
reactionsReader.reactions$,
|
||||
@@ -165,6 +171,7 @@ export const ActiveCall: FC<ActiveCallProps> = (props) => {
|
||||
mediaDevices,
|
||||
trackProcessorState$,
|
||||
props.client,
|
||||
rootElement,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -625,6 +632,9 @@ export const InCallView: FC<InCallViewProps> = ({
|
||||
[styles.overflowing]: overflowing,
|
||||
})}
|
||||
ref={containerRef}
|
||||
// Which layout the call has settled on, for tests and for anyone
|
||||
// wondering why the call looks the way it does at the size it was given
|
||||
data-layout={layout.type}
|
||||
onPointerUp={onViewPointerUp}
|
||||
onPointerMove={onPointerMove}
|
||||
onPointerOut={onPointerOut}
|
||||
|
||||
@@ -4,6 +4,7 @@ exports[`InCallView > rendering > renders 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="_inRoom_4e7ff8"
|
||||
data-layout="one-on-one-desktop"
|
||||
>
|
||||
<header
|
||||
class="_header_e4b327 _header_4e7ff8"
|
||||
|
||||
Reference in New Issue
Block a user