/* Copyright 2024 New Vector Ltd. SPDX-License-Identifier: AGPL-3.0-only Please see LICENSE in the repository root for full details. */ import { type CSSProperties, forwardRef } from "react"; import { useObservableEagerState } from "observable-hooks"; import classNames from "classnames"; import { type CallLayout, arrangeTiles } from "./CallLayout"; import { type SpotlightPortraitLayout as SpotlightPortraitLayoutModel } from "../state/CallViewModel"; import styles from "./SpotlightPortraitLayout.module.css"; import { useUpdateLayout, useVisibleTiles } from "./Grid"; interface GridCSSProperties extends CSSProperties { "--grid-gap": string; "--grid-tile-width": string; "--grid-tile-height": string; } /** * An implementation of the "spotlight portrait" layout, in which the spotlight * tile is shown across the top of the screen, and the grid of participants * scrolls behind it. */ export const makeSpotlightPortraitLayout: CallLayout< SpotlightPortraitLayoutModel > = ({ minBounds$ }) => ({ scrollingOnTop: false, fixed: forwardRef(function SpotlightPortraitLayoutFixed( { model, Slot }, ref, ) { useUpdateLayout(); return (
); }), scrolling: forwardRef(function SpotlightPortraitLayoutScrolling( { model, Slot }, ref, ) { useUpdateLayout(); useVisibleTiles(model.setVisibleTiles); const { width } = useObservableEagerState(minBounds$); const { gap, tileWidth, tileHeight } = arrangeTiles( width, // TODO: We pretend that the minimum height is the width, because the // actual minimum height is difficult to calculate width, model.grid.length, ); const withIndicators = useObservableEagerState(model.spotlight.media$).length > 1; return (
{model.grid.map((m) => ( ))}
); }), });