/* Copyright 2026 Element Creations Ltd. SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ import { type FC, type JSX, type Ref, useMemo } from "react"; import classNames from "classnames"; import LogoMark from "../icons/LogoMark.svg?react"; import LogoType from "../icons/LogoType.svg?react"; import { EndCallButton, MicButton, VideoButton, ShareScreenButton, SettingsButton, ReactionToggleButton, LoudspeakerButton, } from "../button"; import styles from "./InCallFooter.module.css"; import { LayoutToggle } from "../room/LayoutToggle"; import { type CallViewModel, type GridMode, } from "../state/CallViewModel/CallViewModel"; import { useAppBarSecondaryButton } from "../AppBar"; export interface AudioOutputSwitcher { targetOutput: string; switch: () => void; } export interface InCallFooterProps { ref?: Ref; /* This is needed for WindowMode = "flat" */ asOverlay: boolean; showFooter: boolean; showControls: boolean; hideSettingsButton: boolean; hideLogo: boolean; asPip: boolean; gridMode: GridMode; setGridMode: (mode: GridMode) => void; openSettings: () => void; audioEnabled: boolean; videoEnabled: boolean; toggleAudio?: () => void; toggleVideo?: () => void; sharingScreen: boolean; toggleScreenSharing?: () => void; supportsReactions: boolean; reactionIdentifier: string; reactionData: Pick; audioOutputSwitcher: AudioOutputSwitcher | null; hangup: () => void; debugTileLayout: boolean; tileStoreGeneration: number; } export const InCallFooter: FC = ({ ref, asOverlay, showFooter, showControls, hideSettingsButton, hideLogo, asPip, gridMode, setGridMode, openSettings, audioEnabled, videoEnabled, toggleAudio, toggleVideo, sharingScreen, toggleScreenSharing, supportsReactions, reactionIdentifier, reactionData, audioOutputSwitcher, hangup, debugTileLayout, tileStoreGeneration, }) => { const buttons: JSX.Element[] = []; const buttonSize = asPip ? "sm" : "lg"; const showSettingsButton = !hideSettingsButton && !asPip && showControls; const showLayoutSwitcher = !asPip && showControls; const showLogoDebugContainer = !asPip || (!hideLogo && !debugTileLayout); const showLogo = !hideLogo && !asPip; if (showSettingsButton) { // add the settings button to the center group of buttons, so it will be visible on small screens. // On larger screens, it will be hidden and the one without `forButtonsBar` in the `settingsLogoContainer` will be visible. buttons.push( , ); } buttons.push( , , ); if (toggleScreenSharing !== null) { buttons.push( , ); } if (supportsReactions) { buttons.push( , ); } // In this PR we just move the button to the bottom bar. We do not yet update its appearance const audioOutputButton = useMemo(() => { if (audioOutputSwitcher === null) return null; return ( audioOutputSwitcher.switch()} isEarpieceTarget={audioOutputSwitcher.targetOutput === "earpiece"} /> ); }, [audioOutputSwitcher, buttonSize]); if (audioOutputButton) buttons.push(audioOutputButton); useAppBarSecondaryButton( // ,
, ); buttons.push( , ); const logoDebugContainer = (
{showLogo && ( <> )} {debugTileLayout ? `Tiles generation: ${tileStoreGeneration}` : undefined}
); return (
{showSettingsButton && ( )} {showLogoDebugContainer && logoDebugContainer}
{showControls &&
{buttons}
} {showLayoutSwitcher && ( )}
); };