diff --git a/public/locales/en-GB/app.json b/public/locales/en-GB/app.json index b2bfc56..809f5e4 100644 --- a/public/locales/en-GB/app.json +++ b/public/locales/en-GB/app.json @@ -124,6 +124,7 @@ "Turn off camera": "Turn off camera", "Turn on camera": "Turn on camera", "Unmute microphone": "Unmute microphone", + "Use the upcoming grid system": "Use the upcoming grid system", "User ID": "User ID", "User menu": "User menu", "Username": "Username", diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index d4717c1..17a0fde 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -41,7 +41,11 @@ import { RoomHeaderInfo, VersionMismatchWarning, } from "../Header"; -import { VideoGrid, useVideoGridLayout } from "../video-grid/VideoGrid"; +import { + VideoGrid, + useVideoGridLayout, + ChildrenProperties, +} from "../video-grid/VideoGrid"; import { VideoTileContainer } from "../video-grid/VideoTileContainer"; import { GroupCallInspector } from "./GroupCallInspector"; import { OverflowMenu } from "./OverflowMenu"; @@ -296,8 +300,8 @@ export function InCallView({ if (maximisedParticipant) { return ( - {({ - item, - ...rest - }: { - item: TileDescriptor; - [x: string]: unknown; - }) => ( + {({ item, ...rest }: ChildrenProperties) => ( ( ref.current = value; } }), + // Since this isn't an array literal, we can't use the static dependency + // checker, but that's okay + // eslint-disable-next-line react-hooks/exhaustive-deps refs ); diff --git a/src/video-grid/NewVideoGrid.tsx b/src/video-grid/NewVideoGrid.tsx index 810946b..a32c6b4 100644 --- a/src/video-grid/NewVideoGrid.tsx +++ b/src/video-grid/NewVideoGrid.tsx @@ -28,11 +28,12 @@ import React, { useState, } from "react"; import useMeasure from "react-use-measure"; +import { zipWith } from "lodash"; + import styles from "./NewVideoGrid.module.css"; import { TileDescriptor } from "./TileDescriptor"; -import { VideoGridProps as Props } from "./VideoGrid"; +import { VideoGridProps as Props, TileSpring } from "./VideoGrid"; import { useReactiveState } from "../useReactiveState"; -import { zipWith } from "lodash"; import { useMergedRefs } from "../useMergedRefs"; import { Grid, @@ -129,17 +130,6 @@ interface Tile extends Rect { item: TileDescriptor; } -interface TileSpring { - opacity: number; - scale: number; - shadow: number; - zIndex: number; - x: number; - y: number; - width: number; - height: number; -} - interface DragState { tileId: string; tileX: number; @@ -208,7 +198,10 @@ export const NewVideoGrid: FC = ({ } return rects; - }, [items, slotGridGeneration, slotGrid, gridBounds]); + // The rects may change due to the grid being resized or rerendered, but + // eslint can't statically verify this + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [slotGrid, slotGridGeneration, gridBounds]); const [columns] = useReactiveState( // Since grid resizing isn't implemented yet, pick a column count on mount diff --git a/src/video-grid/VideoGrid.tsx b/src/video-grid/VideoGrid.tsx index cb94e40..6623eee 100644 --- a/src/video-grid/VideoGrid.tsx +++ b/src/video-grid/VideoGrid.tsx @@ -16,7 +16,12 @@ limitations under the License. import React, { Key, useCallback, useEffect, useRef, useState } from "react"; import { FullGestureState, useDrag, useGesture } from "@use-gesture/react"; -import { Interpolation, SpringValue, useSprings } from "@react-spring/web"; +import { + SpringRef, + SpringValue, + SpringValues, + useSprings, +} from "@react-spring/web"; import useMeasure from "react-use-measure"; import { ResizeObserver } from "@juggle/resize-observer"; import { ReactDOMAttributes } from "@use-gesture/react/dist/declarations/src/types"; @@ -42,6 +47,17 @@ interface Tile { presenter: boolean; } +export interface TileSpring { + opacity: number; + scale: number; + shadow: number; + zIndex: number; + x: number; + y: number; + width: number; + height: number; +} + type LayoutDirection = "vertical" | "horizontal"; export function useVideoGridLayout(hasScreenshareFeeds: boolean): { @@ -692,7 +708,7 @@ interface DragTileData { y: number; } -interface ChildrenProperties extends ReactDOMAttributes { +export interface ChildrenProperties extends ReactDOMAttributes { key: Key; targetWidth: number; targetHeight: number; @@ -970,7 +986,7 @@ export function VideoGrid({ tilePositions, tiles, scrollPosition, - ]); + ]) as unknown as [SpringValues[], SpringRef]; const onTap = useCallback( (tileKey: Key) => { @@ -1191,7 +1207,6 @@ export function VideoGrid({ targetWidth: tilePosition.width, targetHeight: tilePosition.height, item: tile.item, - onDragRef: onTileDragRef, }); })} diff --git a/src/video-grid/VideoTile.tsx b/src/video-grid/VideoTile.tsx index ca9ebbe..eea617f 100644 --- a/src/video-grid/VideoTile.tsx +++ b/src/video-grid/VideoTile.tsx @@ -44,14 +44,14 @@ interface Props { showOptions?: boolean; isLocal?: boolean; disableSpeakingIndicator?: boolean; - opacity: SpringValue; - scale: SpringValue; - shadow: SpringValue; - zIndex: SpringValue; - x: SpringValue; - y: SpringValue; - width: SpringValue; - height: SpringValue; + opacity?: SpringValue; + scale?: SpringValue; + shadow?: SpringValue; + zIndex?: SpringValue; + x?: SpringValue; + y?: SpringValue; + width?: SpringValue; + height?: SpringValue; } export const VideoTile = forwardRef( @@ -141,14 +141,17 @@ export const VideoTile = forwardRef( style={{ opacity, scale, - boxShadow: shadow.to( + boxShadow: shadow?.to( (s) => `rgba(0, 0, 0, 0.5) 0px ${s}px ${2 * s}px 0px` ), zIndex, x, y, - "--tileWidth": width.to((w) => `${w}px`), - "--tileHeight": height.to((h) => `${h}px`), + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore React does in fact support assigning custom properties, + // but React's types say no + "--tileWidth": width?.to((w) => `${w}px`), + "--tileHeight": height?.to((h) => `${h}px`), }} ref={ref as ForwardedRef} {...rest} diff --git a/src/video-grid/VideoTileContainer.tsx b/src/video-grid/VideoTileContainer.tsx index 8614033..c3a4c61 100644 --- a/src/video-grid/VideoTileContainer.tsx +++ b/src/video-grid/VideoTileContainer.tsx @@ -18,6 +18,8 @@ import { SDPStreamMetadataPurpose } from "matrix-js-sdk/src/webrtc/callEventType import React, { FC, memo, RefObject } from "react"; import { useCallback } from "react"; import { RoomMember } from "matrix-js-sdk/src/models/room-member"; +import { SpringValue } from "@react-spring/web"; +import { EventTypes, Handler, useDrag } from "@use-gesture/react"; import { useCallFeed } from "./useCallFeed"; import { useSpatialMediaStream } from "./useMediaStream"; @@ -26,8 +28,6 @@ import { VideoTile } from "./VideoTile"; import { VideoTileSettingsModal } from "./VideoTileSettingsModal"; import { useModalTriggerState } from "../Modal"; import { TileDescriptor } from "./TileDescriptor"; -import { SpringValue } from "@react-spring/web"; -import { EventTypes, Handler, useDrag } from "@use-gesture/react"; interface Props { item: TileDescriptor; @@ -44,14 +44,14 @@ interface Props { maximised: boolean; fullscreen: boolean; onFullscreen: (item: TileDescriptor) => void; - opacity: SpringValue; - scale: SpringValue; - shadow: SpringValue; - zIndex: SpringValue; - x: SpringValue; - y: SpringValue; - width: SpringValue; - height: SpringValue; + opacity?: SpringValue; + scale?: SpringValue; + shadow?: SpringValue; + zIndex?: SpringValue; + x?: SpringValue; + y?: SpringValue; + width?: SpringValue; + height?: SpringValue; onDragRef?: RefObject< ( tileId: string, diff --git a/src/video-grid/model.ts b/src/video-grid/model.ts index 7d9729c..48f19b3 100644 --- a/src/video-grid/model.ts +++ b/src/video-grid/model.ts @@ -15,6 +15,7 @@ limitations under the License. */ import TinyQueue from "tinyqueue"; + import { TileDescriptor } from "./TileDescriptor"; /**