mirror of
https://github.com/vector-im/element-call.git
synced 2026-09-22 22:29:30 +00:00
Size the device list to the call as it changes
- The bound was taken once when the menu opened, so a host resizing the space Element Call is drawn in while the menu is open left it describing a call area that no longer exists. - Follow it with observeElementSize$, which was already here and already used by useRootSizeMatches, and only while the menu is open. - Quantised before it reaches React, so a drag-resize re-renders only when the bound itself moves. - 160 and 0.6 are named now, with the reason each exists.
This commit is contained in:
@@ -28,6 +28,7 @@ import {
|
||||
} from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
import classNames from "classnames";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { distinctUntilChanged, map } from "rxjs";
|
||||
|
||||
import styles from "./MediaMuteAndSwitchButton.module.css";
|
||||
import { MicButton, VideoButton } from "../button";
|
||||
@@ -37,6 +38,7 @@ import {
|
||||
} from "../state/MediaDevices";
|
||||
import { useMediaDevices } from "../MediaDevicesContext";
|
||||
import { useRootElement } from "../RootElementContext";
|
||||
import { observeElementSize$ } from "../utils/elementSize";
|
||||
import { MicrophoneLevelMeter } from "./MicrophoneLevelMeter";
|
||||
import { useMicrophoneLevel } from "./useMicrophoneLevel";
|
||||
|
||||
@@ -93,6 +95,23 @@ const BLUR_ID = "blur";
|
||||
*/
|
||||
const DEFAULT_OUTPUT_ID = "default";
|
||||
|
||||
/**
|
||||
* The share of the call area the device list may fill.
|
||||
*
|
||||
* The menu carries its headings and the level meter as well, and a list that
|
||||
* took the whole call would hide the call it belongs to.
|
||||
*/
|
||||
const LIST_SHARE_OF_CALL = 0.6;
|
||||
|
||||
/**
|
||||
* The shortest the device list may be, whatever the call measures.
|
||||
*
|
||||
* A share alone collapses in a small call to a list that shows one device and
|
||||
* gives no sign that there are others. Scrolling a short list is the better
|
||||
* failure.
|
||||
*/
|
||||
const MIN_LIST_HEIGHT = 160;
|
||||
|
||||
export const MediaMuteAndSwitchButton: FC<MediaMuteAndSwitchButtonProps> = ({
|
||||
title,
|
||||
enabled,
|
||||
@@ -153,11 +172,25 @@ export const MediaMuteAndSwitchButton: FC<MediaMuteAndSwitchButtonProps> = ({
|
||||
if (menuOpen) setFocusModality("pointer");
|
||||
}, [menuOpen]);
|
||||
useEffect(() => {
|
||||
if (menuOpen)
|
||||
setListMaxHeight(
|
||||
Math.max(160, Math.round(rootElement.clientHeight * 0.6)),
|
||||
);
|
||||
if (!menuOpen) return;
|
||||
// Followed rather than measured once: a host can resize the space Element
|
||||
// Call is drawn in while the menu is open — a panel animating, a window
|
||||
// dragged, a phone turned — and a bound taken on opening then describes a
|
||||
// call area that no longer exists. Quantised before it reaches React, so a
|
||||
// resize re-renders only when the bound itself moves.
|
||||
const subscription = observeElementSize$(rootElement)
|
||||
.pipe(
|
||||
map(({ height }) =>
|
||||
Math.max(MIN_LIST_HEIGHT, Math.round(height * LIST_SHARE_OF_CALL)),
|
||||
),
|
||||
distinctUntilChanged(),
|
||||
)
|
||||
.subscribe(setListMaxHeight);
|
||||
return (): void => subscription.unsubscribe();
|
||||
}, [menuOpen, rootElement]);
|
||||
|
||||
// Only while the menu is open, so nothing holds a second capture of the
|
||||
// microphone for the length of a call.
|
||||
const microphoneState = useMicrophoneLevel(
|
||||
selectedOption,
|
||||
menuOpen && iconsAndLabels === "audio",
|
||||
|
||||
Reference in New Issue
Block a user