import React, { useState, useMemo, useEffect, useRef } from 'react';
import Tile from '@dailyjs/shared/components/Tile';
import { DEFAULT_ASPECT_RATIO } from '@dailyjs/shared/constants';
import { useParticipants } from '@dailyjs/shared/contexts/ParticipantsProvider';
import { useTracks } from '@dailyjs/shared/contexts/TracksProvider';
import { useDeepCompareMemo } from 'use-deep-compare';
export const VideoGrid = React.memo(
() => {
const containerRef = useRef();
const { allParticipants } = useParticipants();
const { resumeVideoTrack } = useTracks();
const [dimensions, setDimensions] = useState({
width: 1,
height: 1,
});
useEffect(() => {
let frame;
const handleResize = () => {
if (frame) cancelAnimationFrame(frame);
frame = requestAnimationFrame(() =>
setDimensions({
width: containerRef.current?.clientWidth,
height: containerRef.current?.clientHeight,
})
);
};
handleResize();
window.addEventListener('resize', handleResize);
window.addEventListener('orientationchange', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
window.removeEventListener('orientationchange', handleResize);
};
}, []);
const layout = useMemo(() => {
const aspectRatio = DEFAULT_ASPECT_RATIO;
const tileCount = allParticipants.length || 0;
const w = dimensions.width;
const h = dimensions.height;
// brute-force search layout where video occupy the largest area of the container
let bestLayout = {
area: 0,
cols: 0,
rows: 0,
width: 0,
height: 0,
};
for (let cols = 0; cols <= tileCount; cols += 1) {
const rows = Math.ceil(tileCount / cols);
const hScale = w / (cols * aspectRatio);
const vScale = h / rows;
let width;
let height;
if (hScale <= vScale) {
width = Math.floor(w / cols);
height = Math.floor(width / aspectRatio);
} else {
height = Math.floor(h / rows);
width = Math.floor(height * aspectRatio);
}
const area = width * height;
if (area > bestLayout.area) {
bestLayout = {
area,
width,
height,
rows,
cols,
};
}
}
return bestLayout;
}, [dimensions, allParticipants]);
const tiles = useDeepCompareMemo(
() =>
allParticipants.map((p) => (