Update the grid layout whenever someone screenshares (uses participant bar)
This commit is contained in:
parent
209b9bd72e
commit
22b4afbb34
|
|
@ -1,13 +1,54 @@
|
|||
import React from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import ExpiryTimer from '@custom/shared/components/ExpiryTimer';
|
||||
import { useCallState } from '@custom/shared/contexts/CallProvider';
|
||||
import { useCallUI } from '@custom/shared/hooks/useCallUI';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import App from '@custom/basic-call/components/App';
|
||||
import { ChatProvider } from '../../contexts/ChatProvider';
|
||||
import Room from '../Call/Room';
|
||||
import { Asides } from './Asides';
|
||||
import { Modals } from './Modals';
|
||||
|
||||
// Extend our basic call app component with the chat context
|
||||
export const CustomApp = () => (
|
||||
<ChatProvider>
|
||||
<App />
|
||||
</ChatProvider>
|
||||
);
|
||||
export const App = ({ customComponentForState }) => {
|
||||
const { roomExp, state } = useCallState();
|
||||
|
||||
export default CustomApp;
|
||||
const componentForState = useCallUI({
|
||||
state,
|
||||
room: <Room />,
|
||||
...customComponentForState,
|
||||
});
|
||||
|
||||
// Memoize children to avoid unnecassary renders from HOC
|
||||
return useMemo(
|
||||
() => (
|
||||
<>
|
||||
<ChatProvider>
|
||||
{roomExp && <ExpiryTimer expiry={roomExp} />}
|
||||
<div className="app">
|
||||
{componentForState()}
|
||||
<Modals />
|
||||
<Asides />
|
||||
<style jsx>{`
|
||||
color: white;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.loader {
|
||||
margin: 0 auto;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
</ChatProvider>
|
||||
</>
|
||||
),
|
||||
[componentForState, roomExp]
|
||||
);
|
||||
};
|
||||
|
||||
App.propTypes = {
|
||||
customComponentForState: PropTypes.any,
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
|
@ -1,9 +1,13 @@
|
|||
import React, { useState, useMemo, useEffect, useRef } from 'react';
|
||||
import ParticipantBar from '@custom/shared/components/ParticipantBar';
|
||||
import Tile from '@custom/shared/components/Tile';
|
||||
import { DEFAULT_ASPECT_RATIO } from '@custom/shared/constants';
|
||||
import { useCallState } from '@custom/shared/contexts/CallProvider';
|
||||
import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider';
|
||||
import { useDeepCompareMemo } from 'use-deep-compare';
|
||||
|
||||
const SIDEBAR_WIDTH = 186;
|
||||
|
||||
/**
|
||||
* Basic unpaginated video tile grid, scaled by aspect ratio
|
||||
*
|
||||
|
|
@ -18,7 +22,8 @@ import { useDeepCompareMemo } from 'use-deep-compare';
|
|||
export const VideoGrid = React.memo(
|
||||
() => {
|
||||
const containerRef = useRef();
|
||||
const { allParticipants } = useParticipants();
|
||||
const { allParticipants, participants, screens, localParticipant } = useParticipants();
|
||||
const { showLocalVideo } = useCallState();
|
||||
const [dimensions, setDimensions] = useState({
|
||||
width: 1,
|
||||
height: 1,
|
||||
|
|
@ -45,10 +50,12 @@ export const VideoGrid = React.memo(
|
|||
};
|
||||
}, []);
|
||||
|
||||
const hasScreenshares = useMemo(() => screens.length > 0, [screens]);
|
||||
|
||||
// Basic brute-force packing algo
|
||||
const layout = useMemo(() => {
|
||||
const aspectRatio = DEFAULT_ASPECT_RATIO;
|
||||
const tileCount = allParticipants.length || 0;
|
||||
const tileCount = hasScreenshares ? screens.length : participants.length || 0;
|
||||
const w = dimensions.width;
|
||||
const h = dimensions.height;
|
||||
|
||||
|
|
@ -87,29 +94,73 @@ export const VideoGrid = React.memo(
|
|||
}
|
||||
|
||||
return bestLayout;
|
||||
}, [dimensions, allParticipants]);
|
||||
}, [hasScreenshares, screens.length, participants.length, dimensions.width, dimensions.height]);
|
||||
|
||||
const otherParticipants = useMemo(
|
||||
() => participants.filter(({ isLocal }) => !isLocal),
|
||||
[participants]
|
||||
);
|
||||
|
||||
const fixedItems = useMemo(() => {
|
||||
const items = [];
|
||||
if (showLocalVideo) {
|
||||
items.push(localParticipant);
|
||||
}
|
||||
if (hasScreenshares && otherParticipants.length > 0) {
|
||||
items.push(otherParticipants[0]);
|
||||
}
|
||||
return items;
|
||||
}, [hasScreenshares, localParticipant, otherParticipants, showLocalVideo]);
|
||||
|
||||
const otherItems = useMemo(() => {
|
||||
if (otherParticipants.length > 1) {
|
||||
return otherParticipants.slice(hasScreenshares ? 1 : 0);
|
||||
}
|
||||
return [];
|
||||
}, [hasScreenshares, otherParticipants]);
|
||||
|
||||
// Memoize our tile list to avoid unnecassary re-renders
|
||||
const tiles = useDeepCompareMemo(
|
||||
() =>
|
||||
allParticipants.map((p) => (
|
||||
participants.map((p) => (
|
||||
<Tile
|
||||
participant={p}
|
||||
key={p.id}
|
||||
mirrored={!p.isScreenshare}
|
||||
mirrored
|
||||
style={{ maxWidth: layout.width, maxHeight: layout.height }}
|
||||
/>
|
||||
)),
|
||||
[layout, allParticipants]
|
||||
[layout, participants]
|
||||
);
|
||||
|
||||
if (!allParticipants.length) {
|
||||
return null;
|
||||
}
|
||||
const screenShareTiles = useDeepCompareMemo(
|
||||
() =>
|
||||
screens.map((p) => (
|
||||
<Tile
|
||||
participant={p}
|
||||
key={p.id}
|
||||
mirrored={false}
|
||||
style={{ maxWidth: layout.width, maxHeight: layout.height }}
|
||||
/>
|
||||
)),
|
||||
[layout, screens]
|
||||
);
|
||||
|
||||
if (!participants.length) return null;
|
||||
|
||||
return (
|
||||
<div className="video-grid" ref={containerRef}>
|
||||
<div className="tiles">{tiles}</div>
|
||||
<div className="tiles">
|
||||
{screenShareTiles}
|
||||
{!hasScreenshares && tiles}
|
||||
</div>
|
||||
{hasScreenshares && (
|
||||
<ParticipantBar
|
||||
fixed={fixedItems}
|
||||
others={otherItems}
|
||||
width={SIDEBAR_WIDTH}
|
||||
/>
|
||||
)}
|
||||
<style jsx>{`
|
||||
.video-grid {
|
||||
align-items: center;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import GlobalStyle from '@custom/shared/components/GlobalStyle';
|
||||
import Head from 'next/head';
|
||||
import PropTypes from 'prop-types';
|
||||
import { CustomApp } from '../components/App/App';
|
||||
import { App as CustomApp } from '../components/App/App';
|
||||
import ChatAside from '../components/Call/ChatAside';
|
||||
import Tray from '../components/Tray';
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import React, {
|
|||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Tile } from '@custom/shared/components/Tile';
|
||||
import Tile from '@custom/shared/components/Tile';
|
||||
import { DEFAULT_ASPECT_RATIO } from '@custom/shared/constants';
|
||||
import { useCallState } from '@custom/shared/contexts/CallProvider';
|
||||
import { useParticipants } from '@custom/shared/contexts/ParticipantsProvider';
|
||||
|
|
|
|||
Loading…
Reference in New Issue