feat(tile-view): Optimize grid dimnsions.
Now the algorithm that calculates the rows/columns/thumbnail-width/thumbnail-height configuration will go trough all possible configurations and will choose the one that covers with thumbnails the biggest area of the window.
This commit is contained in:
parent
3884862996
commit
e7c4a55add
|
@ -73,6 +73,10 @@
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filmstrip__videos.has-scroll {
|
||||||
|
padding-left: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
.remote-videos {
|
.remote-videos {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
@ -90,7 +94,6 @@
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
margin-bottom: auto;
|
margin-bottom: auto;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
.videocontainer {
|
.videocontainer {
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|
|
@ -216,6 +216,7 @@ export default [
|
||||||
'testing',
|
'testing',
|
||||||
'toolbarButtons',
|
'toolbarButtons',
|
||||||
'toolbarConfig',
|
'toolbarConfig',
|
||||||
|
'tileView',
|
||||||
'transcribingEnabled',
|
'transcribingEnabled',
|
||||||
'useHostPageLocalStorage',
|
'useHostPageLocalStorage',
|
||||||
'useTurnUdp',
|
'useTurnUdp',
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
// @flow
|
// @flow
|
||||||
import type { Dispatch } from 'redux';
|
import type { Dispatch } from 'redux';
|
||||||
|
|
||||||
import { getLocalParticipant, getParticipantById, pinParticipant } from '../base/participants';
|
import {
|
||||||
|
getLocalParticipant,
|
||||||
|
getParticipantById,
|
||||||
|
pinParticipant
|
||||||
|
} from '../base/participants';
|
||||||
import { shouldHideSelfView } from '../base/settings/functions.any';
|
import { shouldHideSelfView } from '../base/settings/functions.any';
|
||||||
import { getTileViewGridDimensions } from '../video-layout';
|
import { getMaxColumnCount } from '../video-layout';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SET_FILMSTRIP_WIDTH,
|
SET_FILMSTRIP_WIDTH,
|
||||||
|
@ -21,15 +25,20 @@ import {
|
||||||
TILE_HORIZONTAL_MARGIN,
|
TILE_HORIZONTAL_MARGIN,
|
||||||
TILE_VERTICAL_CONTAINER_HORIZONTAL_MARGIN,
|
TILE_VERTICAL_CONTAINER_HORIZONTAL_MARGIN,
|
||||||
TILE_VERTICAL_MARGIN,
|
TILE_VERTICAL_MARGIN,
|
||||||
|
TILE_VIEW_DEFAULT_NUMBER_OF_VISIBLE_TILES,
|
||||||
|
TILE_VIEW_GRID_HORIZONTAL_MARGIN,
|
||||||
|
TILE_VIEW_GRID_VERTICAL_MARGIN,
|
||||||
VERTICAL_FILMSTRIP_VERTICAL_MARGIN
|
VERTICAL_FILMSTRIP_VERTICAL_MARGIN
|
||||||
} from './constants';
|
} from './constants';
|
||||||
import {
|
import {
|
||||||
|
calculateNotResponsiveTileViewDimensions,
|
||||||
|
calculateResponsiveTileViewDimensions,
|
||||||
calculateThumbnailSizeForHorizontalView,
|
calculateThumbnailSizeForHorizontalView,
|
||||||
calculateThumbnailSizeForTileView,
|
|
||||||
calculateThumbnailSizeForVerticalView,
|
calculateThumbnailSizeForVerticalView,
|
||||||
isFilmstripResizable,
|
isFilmstripResizable,
|
||||||
showGridInVerticalView
|
showGridInVerticalView
|
||||||
} from './functions';
|
} from './functions';
|
||||||
|
import { getNumberOfPartipantsForTileView } from './functions.web';
|
||||||
|
|
||||||
export * from './actions.any';
|
export * from './actions.any';
|
||||||
|
|
||||||
|
@ -41,37 +50,56 @@ export * from './actions.any';
|
||||||
* resolved to Redux state using the {@code toState} function.
|
* resolved to Redux state using the {@code toState} function.
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
export function setTileViewDimensions(dimensions: Object) {
|
export function setTileViewDimensions() {
|
||||||
return (dispatch: Dispatch<any>, getState: Function) => {
|
return (dispatch: Dispatch<any>, getState: Function) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const { clientHeight, clientWidth } = state['features/base/responsive-ui'];
|
const { clientHeight, clientWidth } = state['features/base/responsive-ui'];
|
||||||
const { disableResponsiveTiles, disableTileEnlargement } = state['features/base/config'];
|
const {
|
||||||
|
disableResponsiveTiles,
|
||||||
|
disableTileEnlargement,
|
||||||
|
tileView = {}
|
||||||
|
} = state['features/base/config'];
|
||||||
|
const { numberOfVisibleTiles = TILE_VIEW_DEFAULT_NUMBER_OF_VISIBLE_TILES } = tileView;
|
||||||
|
const numberOfParticipants = getNumberOfPartipantsForTileView(state);
|
||||||
|
const maxColumns = getMaxColumnCount(state);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
height,
|
height,
|
||||||
width
|
width,
|
||||||
} = calculateThumbnailSizeForTileView({
|
columns,
|
||||||
...dimensions,
|
rows
|
||||||
clientWidth,
|
} = disableResponsiveTiles
|
||||||
clientHeight,
|
? calculateNotResponsiveTileViewDimensions(state)
|
||||||
disableResponsiveTiles,
|
: calculateResponsiveTileViewDimensions({
|
||||||
disableTileEnlargement
|
clientWidth,
|
||||||
});
|
clientHeight,
|
||||||
const { columns, rows } = dimensions;
|
disableTileEnlargement,
|
||||||
|
isVerticalFilmstrip: false,
|
||||||
|
maxColumns,
|
||||||
|
numberOfParticipants,
|
||||||
|
numberOfVisibleTiles
|
||||||
|
});
|
||||||
const thumbnailsTotalHeight = rows * (TILE_VERTICAL_MARGIN + height);
|
const thumbnailsTotalHeight = rows * (TILE_VERTICAL_MARGIN + height);
|
||||||
const hasScroll = clientHeight < thumbnailsTotalHeight;
|
const hasScroll = clientHeight < thumbnailsTotalHeight;
|
||||||
const filmstripWidth = (columns * (TILE_HORIZONTAL_MARGIN + width)) + (hasScroll ? SCROLL_SIZE : 0);
|
const filmstripWidth
|
||||||
const filmstripHeight = Math.min(clientHeight, thumbnailsTotalHeight);
|
= Math.min(clientWidth - TILE_VIEW_GRID_HORIZONTAL_MARGIN, columns * (TILE_HORIZONTAL_MARGIN + width))
|
||||||
|
+ (hasScroll ? SCROLL_SIZE : 0);
|
||||||
|
const filmstripHeight = Math.min(clientHeight - TILE_VIEW_GRID_VERTICAL_MARGIN, thumbnailsTotalHeight);
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: SET_TILE_VIEW_DIMENSIONS,
|
type: SET_TILE_VIEW_DIMENSIONS,
|
||||||
dimensions: {
|
dimensions: {
|
||||||
gridDimensions: dimensions,
|
gridDimensions: {
|
||||||
|
columns,
|
||||||
|
rows
|
||||||
|
},
|
||||||
thumbnailSize: {
|
thumbnailSize: {
|
||||||
height,
|
height,
|
||||||
width
|
width
|
||||||
},
|
},
|
||||||
filmstripHeight,
|
filmstripHeight,
|
||||||
filmstripWidth
|
filmstripWidth,
|
||||||
|
hasScroll
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -97,26 +125,34 @@ export function setVerticalViewDimensions() {
|
||||||
|
|
||||||
// grid view in the vertical filmstrip
|
// grid view in the vertical filmstrip
|
||||||
if (_verticalViewGrid) {
|
if (_verticalViewGrid) {
|
||||||
const dimensions = getTileViewGridDimensions(state, filmstripWidth.current);
|
const { tileView = {} } = state['features/base/config'];
|
||||||
|
const { numberOfVisibleTiles = TILE_VIEW_DEFAULT_NUMBER_OF_VISIBLE_TILES } = tileView;
|
||||||
|
const numberOfParticipants = getNumberOfPartipantsForTileView(state);
|
||||||
|
const maxColumns = getMaxColumnCount(state);
|
||||||
const {
|
const {
|
||||||
height,
|
height,
|
||||||
width
|
width,
|
||||||
} = calculateThumbnailSizeForTileView({
|
columns,
|
||||||
...dimensions,
|
rows
|
||||||
|
} = calculateResponsiveTileViewDimensions({
|
||||||
clientWidth: filmstripWidth.current,
|
clientWidth: filmstripWidth.current,
|
||||||
clientHeight,
|
clientHeight,
|
||||||
disableResponsiveTiles: false,
|
|
||||||
disableTileEnlargement: false,
|
disableTileEnlargement: false,
|
||||||
isVerticalFilmstrip: true
|
isVerticalFilmstrip: true,
|
||||||
|
maxColumns,
|
||||||
|
numberOfParticipants,
|
||||||
|
numberOfVisibleTiles
|
||||||
});
|
});
|
||||||
const { columns, rows } = dimensions;
|
|
||||||
const thumbnailsTotalHeight = rows * (TILE_VERTICAL_MARGIN + height);
|
const thumbnailsTotalHeight = rows * (TILE_VERTICAL_MARGIN + height);
|
||||||
const hasScroll = clientHeight < thumbnailsTotalHeight;
|
const hasScroll = clientHeight < thumbnailsTotalHeight;
|
||||||
const widthOfFilmstrip = (columns * (TILE_HORIZONTAL_MARGIN + width)) + (hasScroll ? SCROLL_SIZE : 0);
|
const widthOfFilmstrip = (columns * (TILE_HORIZONTAL_MARGIN + width)) + (hasScroll ? SCROLL_SIZE : 0);
|
||||||
const filmstripHeight = Math.min(clientHeight, thumbnailsTotalHeight);
|
const filmstripHeight = Math.min(clientHeight, thumbnailsTotalHeight);
|
||||||
|
|
||||||
gridView = {
|
gridView = {
|
||||||
gridDimensions: dimensions,
|
gridDimensions: {
|
||||||
|
columns,
|
||||||
|
rows
|
||||||
|
},
|
||||||
thumbnailSize: {
|
thumbnailSize: {
|
||||||
height,
|
height,
|
||||||
width
|
width
|
||||||
|
|
|
@ -767,6 +767,7 @@ function _mapStateToProps(state) {
|
||||||
gridDimensions: dimensions = {},
|
gridDimensions: dimensions = {},
|
||||||
filmstripHeight,
|
filmstripHeight,
|
||||||
filmstripWidth,
|
filmstripWidth,
|
||||||
|
hasScroll = false,
|
||||||
thumbnailSize: tileViewThumbnailSize
|
thumbnailSize: tileViewThumbnailSize
|
||||||
} = state['features/filmstrip'].tileViewDimensions;
|
} = state['features/filmstrip'].tileViewDimensions;
|
||||||
const _currentLayout = getCurrentLayout(state);
|
const _currentLayout = getCurrentLayout(state);
|
||||||
|
@ -796,7 +797,7 @@ function _mapStateToProps(state) {
|
||||||
const shouldReduceHeight = reduceHeight && (
|
const shouldReduceHeight = reduceHeight && (
|
||||||
isMobileBrowser() || _currentLayout !== LAYOUTS.VERTICAL_FILMSTRIP_VIEW);
|
isMobileBrowser() || _currentLayout !== LAYOUTS.VERTICAL_FILMSTRIP_VIEW);
|
||||||
|
|
||||||
const videosClassName = `filmstrip__videos${visible ? '' : ' hidden'}`;
|
let videosClassName = `filmstrip__videos${visible ? '' : ' hidden'}`;
|
||||||
const className = `${remoteVideosVisible || _verticalViewGrid ? '' : 'hide-videos'} ${
|
const className = `${remoteVideosVisible || _verticalViewGrid ? '' : 'hide-videos'} ${
|
||||||
shouldReduceHeight ? 'reduce-height' : ''
|
shouldReduceHeight ? 'reduce-height' : ''
|
||||||
} ${shiftRight ? 'shift-right' : ''} ${collapseTileView ? 'collapse' : ''} ${visible ? '' : 'hidden'}`.trim();
|
} ${shiftRight ? 'shift-right' : ''} ${collapseTileView ? 'collapse' : ''} ${visible ? '' : 'hidden'}`.trim();
|
||||||
|
@ -804,6 +805,9 @@ function _mapStateToProps(state) {
|
||||||
|
|
||||||
switch (_currentLayout) {
|
switch (_currentLayout) {
|
||||||
case LAYOUTS.TILE_VIEW:
|
case LAYOUTS.TILE_VIEW:
|
||||||
|
if (hasScroll) {
|
||||||
|
videosClassName += ' has-scroll';
|
||||||
|
}
|
||||||
_thumbnailSize = tileViewThumbnailSize;
|
_thumbnailSize = tileViewThumbnailSize;
|
||||||
remoteFilmstripHeight = filmstripHeight - (collapseTileView && filmstripPadding > 0 ? filmstripPadding : 0);
|
remoteFilmstripHeight = filmstripHeight - (collapseTileView && filmstripPadding > 0 ? filmstripPadding : 0);
|
||||||
remoteFilmstripWidth = filmstripWidth;
|
remoteFilmstripWidth = filmstripWidth;
|
||||||
|
|
|
@ -28,16 +28,6 @@ export const SQUARE_TILE_ASPECT_RATIO = 1;
|
||||||
*/
|
*/
|
||||||
export const DISPLAY_DRAWER_THRESHOLD = 512;
|
export const DISPLAY_DRAWER_THRESHOLD = 512;
|
||||||
|
|
||||||
/**
|
|
||||||
* Breakpoint past which a single column view is enforced in tile view.
|
|
||||||
*/
|
|
||||||
export const SINGLE_COLUMN_BREAKPOINT = 300;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Breakpoint past which a two column view is enforced in tile view.
|
|
||||||
*/
|
|
||||||
export const TWO_COLUMN_BREAKPOINT = 1000;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Breakpoint past which the aspect ratio is switched in tile view.
|
* Breakpoint past which the aspect ratio is switched in tile view.
|
||||||
* Also, past this breakpoint, if there are two participants in the conference, we enforce
|
* Also, past this breakpoint, if there are two participants in the conference, we enforce
|
||||||
|
@ -57,9 +47,14 @@ export const TILE_MIN_HEIGHT_SMALL = 150;
|
||||||
export const TILE_MIN_HEIGHT_LARGE = 200;
|
export const TILE_MIN_HEIGHT_LARGE = 200;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aspect ratio for portrait tiles. (height / width).
|
* Aspect ratio for portrait tiles.
|
||||||
*/
|
*/
|
||||||
export const TILE_PORTRAIT_ASPECT_RATIO = 1.3;
|
export const TILE_PORTRAIT_ASPECT_RATIO = 1 / 1.3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default number of visible tiles for tile view.
|
||||||
|
*/
|
||||||
|
export const TILE_VIEW_DEFAULT_NUMBER_OF_VISIBLE_TILES = 25;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default number of columns for tile view.
|
* The default number of columns for tile view.
|
||||||
|
@ -150,14 +145,14 @@ export const TILE_VERTICAL_CONTAINER_HORIZONTAL_MARGIN = 2;
|
||||||
*
|
*
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
export const TILE_VIEW_GRID_VERTICAL_MARGIN = 12;
|
export const TILE_VIEW_GRID_VERTICAL_MARGIN = 14;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The horizontal margin of the tile grid container.
|
* The horizontal margin of the tile grid container.
|
||||||
*
|
*
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
export const TILE_VIEW_GRID_HORIZONTAL_MARGIN = 12;
|
export const TILE_VIEW_GRID_HORIZONTAL_MARGIN = 14;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The height of the whole toolbar.
|
* The height of the whole toolbar.
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
getPinnedParticipant
|
getPinnedParticipant
|
||||||
} from '../base/participants';
|
} from '../base/participants';
|
||||||
import { toState } from '../base/redux';
|
import { toState } from '../base/redux';
|
||||||
|
import { shouldHideSelfView } from '../base/settings/functions.any';
|
||||||
import {
|
import {
|
||||||
getLocalVideoTrack,
|
getLocalVideoTrack,
|
||||||
getTrackByMediaTypeAndParticipant,
|
getTrackByMediaTypeAndParticipant,
|
||||||
|
@ -17,7 +18,11 @@ import {
|
||||||
isRemoteTrackMuted
|
isRemoteTrackMuted
|
||||||
} from '../base/tracks/functions';
|
} from '../base/tracks/functions';
|
||||||
import { isTrackStreamingStatusActive, isParticipantConnectionStatusActive } from '../connection-indicator/functions';
|
import { isTrackStreamingStatusActive, isParticipantConnectionStatusActive } from '../connection-indicator/functions';
|
||||||
import { getCurrentLayout, LAYOUTS } from '../video-layout';
|
import {
|
||||||
|
getCurrentLayout,
|
||||||
|
getNotResponsiveTileViewGridDimensions,
|
||||||
|
LAYOUTS
|
||||||
|
} from '../video-layout';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ASPECT_RATIO_BREAKPOINT,
|
ASPECT_RATIO_BREAKPOINT,
|
||||||
|
@ -27,7 +32,6 @@ import {
|
||||||
DISPLAY_VIDEO,
|
DISPLAY_VIDEO,
|
||||||
FILMSTRIP_GRID_BREAKPOINT,
|
FILMSTRIP_GRID_BREAKPOINT,
|
||||||
INDICATORS_TOOLTIP_POSITION,
|
INDICATORS_TOOLTIP_POSITION,
|
||||||
SCROLL_SIZE,
|
|
||||||
SQUARE_TILE_ASPECT_RATIO,
|
SQUARE_TILE_ASPECT_RATIO,
|
||||||
TILE_ASPECT_RATIO,
|
TILE_ASPECT_RATIO,
|
||||||
TILE_HORIZONTAL_MARGIN,
|
TILE_HORIZONTAL_MARGIN,
|
||||||
|
@ -35,6 +39,7 @@ import {
|
||||||
TILE_MIN_HEIGHT_SMALL,
|
TILE_MIN_HEIGHT_SMALL,
|
||||||
TILE_PORTRAIT_ASPECT_RATIO,
|
TILE_PORTRAIT_ASPECT_RATIO,
|
||||||
TILE_VERTICAL_MARGIN,
|
TILE_VERTICAL_MARGIN,
|
||||||
|
TILE_VIEW_DEFAULT_NUMBER_OF_VISIBLE_TILES,
|
||||||
TILE_VIEW_GRID_HORIZONTAL_MARGIN,
|
TILE_VIEW_GRID_HORIZONTAL_MARGIN,
|
||||||
TILE_VIEW_GRID_VERTICAL_MARGIN,
|
TILE_VIEW_GRID_VERTICAL_MARGIN,
|
||||||
VERTICAL_VIEW_HORIZONTAL_MARGIN
|
VERTICAL_VIEW_HORIZONTAL_MARGIN
|
||||||
|
@ -187,6 +192,211 @@ export function calculateThumbnailSizeForVerticalView(clientWidth: number = 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the minimum height of a thumbnail.
|
||||||
|
*
|
||||||
|
* @param {number} clientWidth - The width of the window.
|
||||||
|
* @returns {number} The minimum height of a thumbnail.
|
||||||
|
*/
|
||||||
|
export function getThumbnailMinHeight(clientWidth) {
|
||||||
|
return clientWidth < ASPECT_RATIO_BREAKPOINT ? TILE_MIN_HEIGHT_SMALL : TILE_MIN_HEIGHT_LARGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the default aspect ratio for a tile.
|
||||||
|
*
|
||||||
|
* @param {boolean} disableResponsiveTiles - Indicates whether the responsive tiles functionality is disabled.
|
||||||
|
* @param {boolean} disableTileEnlargement - Indicates whether the tiles enlargement functionality is disabled.
|
||||||
|
* @param {number} clientWidth - The width of the window.
|
||||||
|
* @returns {number} The default aspect ratio for a tile.
|
||||||
|
*/
|
||||||
|
export function getTileDefaultAspectRatio(disableResponsiveTiles, disableTileEnlargement, clientWidth) {
|
||||||
|
if (!disableResponsiveTiles && disableTileEnlargement && clientWidth < ASPECT_RATIO_BREAKPOINT) {
|
||||||
|
return SQUARE_TILE_ASPECT_RATIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TILE_ASPECT_RATIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of participants that will be displayed in tile view.
|
||||||
|
*
|
||||||
|
* @param {Object} state - The redux store state.
|
||||||
|
* @returns {number} The number of participants that will be displayed in tile view.
|
||||||
|
*/
|
||||||
|
export function getNumberOfPartipantsForTileView(state) {
|
||||||
|
const { iAmRecorder } = state['features/base/config'];
|
||||||
|
const disableSelfView = shouldHideSelfView(state);
|
||||||
|
const numberOfParticipants = getParticipantCountWithFake(state)
|
||||||
|
- (iAmRecorder ? 1 : 0)
|
||||||
|
- (disableSelfView ? 1 : 0);
|
||||||
|
|
||||||
|
return numberOfParticipants;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the dimensions (thumbnail width/height and columns/row) for tile view when the responsive tiles are
|
||||||
|
* disabled.
|
||||||
|
*
|
||||||
|
* @param {Object} state - The redux store state.
|
||||||
|
* @returns {Object} - The dimensions.
|
||||||
|
*/
|
||||||
|
export function calculateNotResponsiveTileViewDimensions(state) {
|
||||||
|
const { clientHeight, clientWidth } = state['features/base/responsive-ui'];
|
||||||
|
const { disableTileEnlargement } = state['features/base/config'];
|
||||||
|
const { columns: c, minVisibleRows, rows: r } = getNotResponsiveTileViewGridDimensions(state);
|
||||||
|
const size = calculateThumbnailSizeForTileView({
|
||||||
|
columns: c,
|
||||||
|
minVisibleRows,
|
||||||
|
clientWidth,
|
||||||
|
clientHeight,
|
||||||
|
disableTileEnlargement,
|
||||||
|
disableResponsiveTiles: true
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof size === 'undefined') { // The columns don't fit into the screen. We will have horizontal scroll.
|
||||||
|
const aspectRatio = disableTileEnlargement
|
||||||
|
? getTileDefaultAspectRatio(true, disableTileEnlargement, clientWidth)
|
||||||
|
: TILE_PORTRAIT_ASPECT_RATIO;
|
||||||
|
|
||||||
|
const height = getThumbnailMinHeight(clientWidth);
|
||||||
|
|
||||||
|
return {
|
||||||
|
height,
|
||||||
|
width: aspectRatio * height,
|
||||||
|
columns: c,
|
||||||
|
rows: r
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
height: size.height,
|
||||||
|
width: size.width,
|
||||||
|
columns: c,
|
||||||
|
rows: r
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the dimensions (thumbnail width/height and columns/row) for tile view when the responsive tiles are
|
||||||
|
* enabled.
|
||||||
|
*
|
||||||
|
* @param {Object} state - The redux store state.
|
||||||
|
* @returns {Object} - The dimensions.
|
||||||
|
*/
|
||||||
|
export function calculateResponsiveTileViewDimensions({
|
||||||
|
clientWidth,
|
||||||
|
clientHeight,
|
||||||
|
disableTileEnlargement = false,
|
||||||
|
isVerticalFilmstrip = false,
|
||||||
|
maxColumns,
|
||||||
|
numberOfParticipants,
|
||||||
|
numberOfVisibleTiles = TILE_VIEW_DEFAULT_NUMBER_OF_VISIBLE_TILES
|
||||||
|
}) {
|
||||||
|
let height, width;
|
||||||
|
let columns, rows;
|
||||||
|
|
||||||
|
let dimensions = {
|
||||||
|
maxArea: 0
|
||||||
|
};
|
||||||
|
let minHeightEnforcedDimensions = {
|
||||||
|
maxArea: 0
|
||||||
|
};
|
||||||
|
let zeroVisibleRowsDimensions = {
|
||||||
|
maxArea: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
for (let c = 1; c <= Math.min(maxColumns, numberOfParticipants); c++) {
|
||||||
|
const r = Math.ceil(numberOfParticipants / c);
|
||||||
|
|
||||||
|
// we want to display as much as possible tumbnails up to numberOfVisibleTiles
|
||||||
|
const visibleRows
|
||||||
|
= numberOfParticipants <= numberOfVisibleTiles ? r : Math.floor(numberOfVisibleTiles / c);
|
||||||
|
|
||||||
|
const size = calculateThumbnailSizeForTileView({
|
||||||
|
columns: c,
|
||||||
|
minVisibleRows: visibleRows,
|
||||||
|
clientWidth,
|
||||||
|
clientHeight,
|
||||||
|
disableTileEnlargement,
|
||||||
|
disableResponsiveTiles: false,
|
||||||
|
isVerticalFilmstrip
|
||||||
|
});
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-negated-condition
|
||||||
|
if (typeof size !== 'undefined') {
|
||||||
|
|
||||||
|
const { height: currentHeight, width: currentWidth, minHeightEnforced, maxVisibleRows } = size;
|
||||||
|
|
||||||
|
console.error(`Num col = ${c}, visibleRows=${visibleRows}, hxw=${
|
||||||
|
currentHeight}x${currentWidth}, maxVisibleRows=${maxVisibleRows}`);
|
||||||
|
let area = currentHeight * currentWidth * Math.min(c * maxVisibleRows, numberOfParticipants);
|
||||||
|
|
||||||
|
// we have a preference to show more columns if possible, that's why even if the area is equal we
|
||||||
|
// overwrite.
|
||||||
|
if (!minHeightEnforced && area > dimensions.maxArea) {
|
||||||
|
dimensions = {
|
||||||
|
maxArea: area,
|
||||||
|
height: currentHeight,
|
||||||
|
width: currentWidth,
|
||||||
|
columns: c,
|
||||||
|
rows: r
|
||||||
|
};
|
||||||
|
} else if (minHeightEnforced) {
|
||||||
|
// eslint-disable-next-line max-depth
|
||||||
|
if (area > minHeightEnforcedDimensions.maxArea) {
|
||||||
|
minHeightEnforcedDimensions = {
|
||||||
|
maxArea: area,
|
||||||
|
height: currentHeight,
|
||||||
|
width: currentWidth,
|
||||||
|
columns: c,
|
||||||
|
rows: r
|
||||||
|
};
|
||||||
|
} else if (maxVisibleRows === 0) {
|
||||||
|
area = currentHeight * currentWidth * Math.min(c, numberOfParticipants);
|
||||||
|
|
||||||
|
// eslint-disable-next-line max-depth
|
||||||
|
if (area > zeroVisibleRowsDimensions.maxArea) {
|
||||||
|
zeroVisibleRowsDimensions = {
|
||||||
|
maxArea: area,
|
||||||
|
height: currentHeight,
|
||||||
|
width: currentWidth,
|
||||||
|
columns: c,
|
||||||
|
rows: r
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error(`Num col = ${c}, visibleRows=${visibleRows} not possible`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dimensions.maxArea > 0) {
|
||||||
|
({ height, width, columns, rows } = dimensions);
|
||||||
|
} else if (minHeightEnforcedDimensions.maxArea > 0) {
|
||||||
|
({ height, width, columns, rows } = minHeightEnforcedDimensions);
|
||||||
|
} else if (zeroVisibleRowsDimensions.maxArea > 0) {
|
||||||
|
({ height, width, columns, rows } = zeroVisibleRowsDimensions);
|
||||||
|
} else { // This would mean that we can't fit even one thumbnail with minimal size.
|
||||||
|
const aspectRatio = disableTileEnlargement
|
||||||
|
? getTileDefaultAspectRatio(false, disableTileEnlargement, clientWidth)
|
||||||
|
: TILE_PORTRAIT_ASPECT_RATIO;
|
||||||
|
|
||||||
|
height = getThumbnailMinHeight(clientWidth);
|
||||||
|
width = aspectRatio * height;
|
||||||
|
columns = 1;
|
||||||
|
rows = numberOfParticipants;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
height,
|
||||||
|
width,
|
||||||
|
columns,
|
||||||
|
rows
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the size for thumbnails when in tile view layout.
|
* Calculates the size for thumbnails when in tile view layout.
|
||||||
*
|
*
|
||||||
|
@ -196,90 +406,78 @@ export function calculateThumbnailSizeForVerticalView(clientWidth: number = 0,
|
||||||
export function calculateThumbnailSizeForTileView({
|
export function calculateThumbnailSizeForTileView({
|
||||||
columns,
|
columns,
|
||||||
minVisibleRows,
|
minVisibleRows,
|
||||||
rows,
|
|
||||||
clientWidth,
|
clientWidth,
|
||||||
clientHeight,
|
clientHeight,
|
||||||
disableResponsiveTiles,
|
disableResponsiveTiles = false,
|
||||||
disableTileEnlargement,
|
disableTileEnlargement = false,
|
||||||
isVerticalFilmstrip = false
|
isVerticalFilmstrip = false
|
||||||
}: Object) {
|
}: Object) {
|
||||||
let aspectRatio = TILE_ASPECT_RATIO;
|
const aspectRatio = getTileDefaultAspectRatio(disableResponsiveTiles, disableTileEnlargement, clientWidth);
|
||||||
|
const minHeight = getThumbnailMinHeight(clientWidth);
|
||||||
if (!disableResponsiveTiles && clientWidth < ASPECT_RATIO_BREAKPOINT) {
|
|
||||||
aspectRatio = SQUARE_TILE_ASPECT_RATIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
const minHeight = clientWidth < ASPECT_RATIO_BREAKPOINT ? TILE_MIN_HEIGHT_SMALL : TILE_MIN_HEIGHT_LARGE;
|
|
||||||
const viewWidth = clientWidth - (columns * TILE_HORIZONTAL_MARGIN)
|
const viewWidth = clientWidth - (columns * TILE_HORIZONTAL_MARGIN)
|
||||||
- (isVerticalFilmstrip ? 0 : TILE_VIEW_GRID_HORIZONTAL_MARGIN);
|
- (isVerticalFilmstrip ? 0 : TILE_VIEW_GRID_HORIZONTAL_MARGIN);
|
||||||
const viewHeight = clientHeight - (minVisibleRows * TILE_VERTICAL_MARGIN) - TILE_VIEW_GRID_VERTICAL_MARGIN;
|
const viewHeight = clientHeight - (minVisibleRows * TILE_VERTICAL_MARGIN) - TILE_VIEW_GRID_VERTICAL_MARGIN;
|
||||||
const initialWidth = viewWidth / columns;
|
const initialWidth = viewWidth / columns;
|
||||||
const initialHeight = viewHeight / minVisibleRows;
|
let initialHeight = viewHeight / minVisibleRows;
|
||||||
const aspectRatioHeight = initialWidth / aspectRatio;
|
let minHeightEnforced = false;
|
||||||
const noScrollHeight = (clientHeight / rows) - TILE_VERTICAL_MARGIN;
|
|
||||||
const scrollInitialWidth = (viewWidth - SCROLL_SIZE) / columns;
|
|
||||||
let height = Math.floor(Math.min(aspectRatioHeight, initialHeight));
|
|
||||||
let width = Math.floor(aspectRatio * height);
|
|
||||||
|
|
||||||
if (height > noScrollHeight && width > scrollInitialWidth) { // we will have scroll and we need more space for it.
|
if (initialHeight < minHeight) {
|
||||||
const scrollAspectRatioHeight = scrollInitialWidth / aspectRatio;
|
minHeightEnforced = true;
|
||||||
|
initialHeight = minHeight;
|
||||||
// Recalculating width/height to fit the available space when a scroll is displayed.
|
|
||||||
// NOTE: Math.min(scrollAspectRatioHeight, initialHeight) would be enough to recalculate but since the new
|
|
||||||
// height value can theoretically be dramatically smaller and the scroll may not be neccessary anymore we need
|
|
||||||
// to compare it with noScrollHeight( the optimal height to fit all thumbnails without scroll) and get the
|
|
||||||
// bigger one. This way we ensure that we always strech the thumbnails as close as we can to the edges of the
|
|
||||||
// window.
|
|
||||||
height = Math.floor(Math.max(Math.min(scrollAspectRatioHeight, initialHeight), noScrollHeight));
|
|
||||||
width = Math.floor(aspectRatio * height);
|
|
||||||
|
|
||||||
return {
|
|
||||||
height,
|
|
||||||
width
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disableTileEnlargement) {
|
if (disableTileEnlargement) {
|
||||||
return {
|
const aspectRatioHeight = initialWidth / aspectRatio;
|
||||||
height,
|
|
||||||
width
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (initialHeight > noScrollHeight) {
|
if (aspectRatioHeight < minHeight) { // we can't fit the required number of columns.
|
||||||
height = Math.max(height, viewHeight / rows, minHeight);
|
return;
|
||||||
width = Math.max(width, initialWidth);
|
|
||||||
} else {
|
|
||||||
height = Math.max(initialHeight, minHeight);
|
|
||||||
width = initialWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (height > width) {
|
|
||||||
const heightFromWidth = TILE_PORTRAIT_ASPECT_RATIO * width;
|
|
||||||
|
|
||||||
if (height > heightFromWidth && heightFromWidth < minHeight) {
|
|
||||||
return {
|
|
||||||
height,
|
|
||||||
width: height / TILE_PORTRAIT_ASPECT_RATIO
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
const height = Math.floor(Math.min(aspectRatioHeight, initialHeight));
|
||||||
height: Math.min(height, heightFromWidth),
|
|
||||||
width
|
|
||||||
};
|
|
||||||
} else if (height < width) {
|
|
||||||
return {
|
return {
|
||||||
height,
|
height,
|
||||||
width: Math.min(width, aspectRatio * height)
|
width: Math.floor(aspectRatio * height),
|
||||||
|
minHeightEnforced,
|
||||||
|
maxVisibleRows: Math.floor(viewHeight / height)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
const initialRatio = initialWidth / initialHeight;
|
||||||
height,
|
let height = Math.floor(initialHeight);
|
||||||
width
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// The biggest area of the grid will be when the grid's height is equal to clientHeight or when the grid's width is
|
||||||
|
// equal to clientWidth.
|
||||||
|
|
||||||
|
if (initialRatio > aspectRatio) {
|
||||||
|
return {
|
||||||
|
height,
|
||||||
|
width: Math.floor(initialHeight * aspectRatio),
|
||||||
|
minHeightEnforced,
|
||||||
|
maxVisibleRows: Math.floor(viewHeight / height)
|
||||||
|
};
|
||||||
|
} else if (initialRatio >= TILE_PORTRAIT_ASPECT_RATIO) {
|
||||||
|
return {
|
||||||
|
height,
|
||||||
|
width: Math.floor(initialWidth),
|
||||||
|
minHeightEnforced,
|
||||||
|
maxVisibleRows: Math.floor(viewHeight / height)
|
||||||
|
};
|
||||||
|
} else if (!minHeightEnforced) {
|
||||||
|
height = Math.floor(initialWidth / TILE_PORTRAIT_ASPECT_RATIO);
|
||||||
|
|
||||||
|
if (height >= minHeight) {
|
||||||
|
return {
|
||||||
|
height,
|
||||||
|
width: Math.floor(initialWidth),
|
||||||
|
minHeightEnforced,
|
||||||
|
maxVisibleRows: Math.floor(viewHeight / height)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// else
|
||||||
|
// We can't fit that number of columns with the desired min height and aspect ratio.
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -44,9 +44,7 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
|
|
||||||
switch (layout) {
|
switch (layout) {
|
||||||
case LAYOUTS.TILE_VIEW: {
|
case LAYOUTS.TILE_VIEW: {
|
||||||
const { gridDimensions } = state['features/filmstrip'].tileViewDimensions;
|
store.dispatch(setTileViewDimensions());
|
||||||
|
|
||||||
store.dispatch(setTileViewDimensions(gridDimensions));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW:
|
case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import { getParticipantCountWithFake } from '../base/participants';
|
import { getParticipantCountWithFake } from '../base/participants';
|
||||||
import { StateListenerRegistry } from '../base/redux';
|
import { StateListenerRegistry } from '../base/redux';
|
||||||
import { getTileViewGridDimensions, shouldDisplayTileView } from '../video-layout';
|
import { shouldDisplayTileView } from '../video-layout';
|
||||||
|
|
||||||
import { setTileViewDimensions } from './actions';
|
import { setTileViewDimensions } from './actions';
|
||||||
import './subscriber.any';
|
import './subscriber.any';
|
||||||
|
@ -34,9 +34,7 @@ StateListenerRegistry.register(
|
||||||
StateListenerRegistry.register(
|
StateListenerRegistry.register(
|
||||||
/* selector */ state => shouldDisplayTileView(state),
|
/* selector */ state => shouldDisplayTileView(state),
|
||||||
/* listener */ (isTileView, store) => {
|
/* listener */ (isTileView, store) => {
|
||||||
const state = store.getState();
|
|
||||||
|
|
||||||
if (isTileView) {
|
if (isTileView) {
|
||||||
store.dispatch(setTileViewDimensions(getTileViewGridDimensions(state)));
|
store.dispatch(setTileViewDimensions());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
import { isMobileBrowser } from '../base/environment/utils';
|
import { isMobileBrowser } from '../base/environment/utils';
|
||||||
import { getParticipantCountWithFake } from '../base/participants';
|
import { getParticipantCountWithFake } from '../base/participants';
|
||||||
import { StateListenerRegistry, equals } from '../base/redux';
|
import { StateListenerRegistry } from '../base/redux';
|
||||||
import { clientResized } from '../base/responsive-ui';
|
import { clientResized } from '../base/responsive-ui';
|
||||||
import { shouldHideSelfView } from '../base/settings';
|
import { shouldHideSelfView } from '../base/settings';
|
||||||
import { setFilmstripVisible } from '../filmstrip/actions';
|
import { setFilmstripVisible } from '../filmstrip/actions';
|
||||||
import { getParticipantsPaneOpen } from '../participants-pane/functions';
|
import { getParticipantsPaneOpen } from '../participants-pane/functions';
|
||||||
import { setOverflowDrawer } from '../toolbox/actions.web';
|
import { setOverflowDrawer } from '../toolbox/actions.web';
|
||||||
import { getCurrentLayout, getTileViewGridDimensions, shouldDisplayTileView, LAYOUTS } from '../video-layout';
|
import { getCurrentLayout, shouldDisplayTileView, LAYOUTS } from '../video-layout';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
setHorizontalViewDimensions,
|
setHorizontalViewDimensions,
|
||||||
|
@ -17,9 +17,7 @@ import {
|
||||||
} from './actions';
|
} from './actions';
|
||||||
import {
|
import {
|
||||||
ASPECT_RATIO_BREAKPOINT,
|
ASPECT_RATIO_BREAKPOINT,
|
||||||
DISPLAY_DRAWER_THRESHOLD,
|
DISPLAY_DRAWER_THRESHOLD
|
||||||
SINGLE_COLUMN_BREAKPOINT,
|
|
||||||
TWO_COLUMN_BREAKPOINT
|
|
||||||
} from './constants';
|
} from './constants';
|
||||||
import { isFilmstripResizable } from './functions.web';
|
import { isFilmstripResizable } from './functions.web';
|
||||||
import './subscriber.any';
|
import './subscriber.any';
|
||||||
|
@ -40,12 +38,7 @@ StateListenerRegistry.register(
|
||||||
const resizableFilmstrip = isFilmstripResizable(state);
|
const resizableFilmstrip = isFilmstripResizable(state);
|
||||||
|
|
||||||
if (shouldDisplayTileView(state)) {
|
if (shouldDisplayTileView(state)) {
|
||||||
const gridDimensions = getTileViewGridDimensions(state);
|
store.dispatch(setTileViewDimensions());
|
||||||
const oldGridDimensions = state['features/filmstrip'].tileViewDimensions.gridDimensions;
|
|
||||||
|
|
||||||
if (!equals(gridDimensions, oldGridDimensions)) {
|
|
||||||
store.dispatch(setTileViewDimensions(gridDimensions));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (resizableFilmstrip) {
|
if (resizableFilmstrip) {
|
||||||
store.dispatch(setVerticalViewDimensions());
|
store.dispatch(setVerticalViewDimensions());
|
||||||
|
@ -60,11 +53,9 @@ StateListenerRegistry.register(
|
||||||
StateListenerRegistry.register(
|
StateListenerRegistry.register(
|
||||||
/* selector */ state => getCurrentLayout(state),
|
/* selector */ state => getCurrentLayout(state),
|
||||||
/* listener */ (layout, store) => {
|
/* listener */ (layout, store) => {
|
||||||
const state = store.getState();
|
|
||||||
|
|
||||||
switch (layout) {
|
switch (layout) {
|
||||||
case LAYOUTS.TILE_VIEW:
|
case LAYOUTS.TILE_VIEW:
|
||||||
store.dispatch(setTileViewDimensions(getTileViewGridDimensions(state)));
|
store.dispatch(setTileViewDimensions());
|
||||||
break;
|
break;
|
||||||
case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW:
|
case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW:
|
||||||
store.dispatch(setHorizontalViewDimensions());
|
store.dispatch(setHorizontalViewDimensions());
|
||||||
|
@ -132,50 +123,6 @@ StateListenerRegistry.register(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Symbol mapping used for the tile view responsiveness computation.
|
|
||||||
*/
|
|
||||||
const responsiveColumnMapping = {
|
|
||||||
multipleColumns: Symbol('multipleColumns'),
|
|
||||||
singleColumn: Symbol('singleColumn'),
|
|
||||||
twoColumns: Symbol('twoColumns'),
|
|
||||||
twoParticipantsSingleColumn: Symbol('twoParticipantsSingleColumn')
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listens for changes in the screen size to recompute
|
|
||||||
* the dimensions of the tile view grid and the tiles for responsiveness.
|
|
||||||
*/
|
|
||||||
StateListenerRegistry.register(
|
|
||||||
/* selector */ state => {
|
|
||||||
const { clientWidth } = state['features/base/responsive-ui'];
|
|
||||||
|
|
||||||
if (clientWidth < TWO_COLUMN_BREAKPOINT && clientWidth >= ASPECT_RATIO_BREAKPOINT) {
|
|
||||||
// Forcing the recomputation of tiles when screen switches in or out of
|
|
||||||
// the (TWO_COLUMN_BREAKPOINT, ASPECT_RATIO_BREAKPOINT] interval.
|
|
||||||
return responsiveColumnMapping.twoColumns;
|
|
||||||
} else if (clientWidth < ASPECT_RATIO_BREAKPOINT && clientWidth >= SINGLE_COLUMN_BREAKPOINT) {
|
|
||||||
// Forcing the recomputation of tiles when screen switches in or out of
|
|
||||||
// the (ASPECT_RATIO_BREAKPOINT, SINGLE_COLUMN_BREAKPOINT] interval.
|
|
||||||
return responsiveColumnMapping.twoParticipantsSingleColumn;
|
|
||||||
} else if (clientWidth < SINGLE_COLUMN_BREAKPOINT) {
|
|
||||||
// Forcing the recomputation of tiles when screen switches below SINGLE_COLUMN_BREAKPOINT.
|
|
||||||
return responsiveColumnMapping.singleColumn;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forcing the recomputation of tiles when screen switches above TWO_COLUMN_BREAKPOINT.
|
|
||||||
return responsiveColumnMapping.multipleColumns;
|
|
||||||
},
|
|
||||||
/* listener */ (_, store) => {
|
|
||||||
const state = store.getState();
|
|
||||||
|
|
||||||
if (shouldDisplayTileView(state)) {
|
|
||||||
const gridDimensions = getTileViewGridDimensions(state);
|
|
||||||
|
|
||||||
store.dispatch(setTileViewDimensions(gridDimensions));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listens for changes in the filmstrip width to determine the size of the tiles.
|
* Listens for changes in the filmstrip width to determine the size of the tiles.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -5,17 +5,13 @@ import { getFeatureFlag, TILE_VIEW_ENABLED } from '../base/flags';
|
||||||
import {
|
import {
|
||||||
getPinnedParticipant,
|
getPinnedParticipant,
|
||||||
getParticipantCount,
|
getParticipantCount,
|
||||||
pinParticipant,
|
pinParticipant
|
||||||
getParticipantCountWithFake
|
|
||||||
} from '../base/participants';
|
} from '../base/participants';
|
||||||
import { shouldHideSelfView } from '../base/settings/functions.any';
|
|
||||||
import {
|
import {
|
||||||
ASPECT_RATIO_BREAKPOINT,
|
|
||||||
DEFAULT_MAX_COLUMNS,
|
DEFAULT_MAX_COLUMNS,
|
||||||
ABSOLUTE_MAX_COLUMNS,
|
ABSOLUTE_MAX_COLUMNS
|
||||||
SINGLE_COLUMN_BREAKPOINT,
|
|
||||||
TWO_COLUMN_BREAKPOINT
|
|
||||||
} from '../filmstrip/constants';
|
} from '../filmstrip/constants';
|
||||||
|
import { getNumberOfPartipantsForTileView } from '../filmstrip/functions.web';
|
||||||
import { isVideoPlaying } from '../shared-video/functions';
|
import { isVideoPlaying } from '../shared-video/functions';
|
||||||
|
|
||||||
import { LAYOUTS } from './constants';
|
import { LAYOUTS } from './constants';
|
||||||
|
@ -62,32 +58,10 @@ export function getCurrentLayout(state: Object) {
|
||||||
* @param {number} width - Custom width to use for calculation.
|
* @param {number} width - Custom width to use for calculation.
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
export function getMaxColumnCount(state: Object, width: ?number) {
|
export function getMaxColumnCount() {
|
||||||
const configuredMax = (typeof interfaceConfig === 'undefined'
|
const configuredMax = (typeof interfaceConfig === 'undefined'
|
||||||
? DEFAULT_MAX_COLUMNS
|
? DEFAULT_MAX_COLUMNS
|
||||||
: interfaceConfig.TILE_VIEW_MAX_COLUMNS) || DEFAULT_MAX_COLUMNS;
|
: interfaceConfig.TILE_VIEW_MAX_COLUMNS) || DEFAULT_MAX_COLUMNS;
|
||||||
const { disableResponsiveTiles } = state['features/base/config'];
|
|
||||||
|
|
||||||
if (!disableResponsiveTiles) {
|
|
||||||
const { clientWidth } = state['features/base/responsive-ui'];
|
|
||||||
const widthToUse = width || clientWidth;
|
|
||||||
const participantCount = getParticipantCount(state);
|
|
||||||
|
|
||||||
// If there are just two participants in a conference, enforce single-column view for mobile size.
|
|
||||||
if (participantCount === 2 && widthToUse < ASPECT_RATIO_BREAKPOINT) {
|
|
||||||
return Math.min(1, Math.max(configuredMax, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enforce single column view at very small screen widths.
|
|
||||||
if (widthToUse < SINGLE_COLUMN_BREAKPOINT) {
|
|
||||||
return Math.min(1, Math.max(configuredMax, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enforce two column view below breakpoint.
|
|
||||||
if (widthToUse < TWO_COLUMN_BREAKPOINT) {
|
|
||||||
return Math.min(2, Math.max(configuredMax, 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Math.min(Math.max(configuredMax, 1), ABSOLUTE_MAX_COLUMNS);
|
return Math.min(Math.max(configuredMax, 1), ABSOLUTE_MAX_COLUMNS);
|
||||||
}
|
}
|
||||||
|
@ -102,22 +76,10 @@ export function getMaxColumnCount(state: Object, width: ?number) {
|
||||||
* @returns {Object} An object is return with the desired number of columns,
|
* @returns {Object} An object is return with the desired number of columns,
|
||||||
* rows, and visible rows (the rest should overflow) for the tile view layout.
|
* rows, and visible rows (the rest should overflow) for the tile view layout.
|
||||||
*/
|
*/
|
||||||
export function getTileViewGridDimensions(state: Object, width: ?number) {
|
export function getNotResponsiveTileViewGridDimensions(state: Object) {
|
||||||
const maxColumns = getMaxColumnCount(state, width);
|
const maxColumns = getMaxColumnCount(state);
|
||||||
|
const numberOfParticipants = getNumberOfPartipantsForTileView(state);
|
||||||
// When in tile view mode, we must discount ourselves (the local participant) because our
|
const columnsToMaintainASquare = Math.ceil(Math.sqrt(numberOfParticipants));
|
||||||
// tile is not visible.
|
|
||||||
const { iAmRecorder } = state['features/base/config'];
|
|
||||||
const disableSelfView = shouldHideSelfView(state);
|
|
||||||
const numberOfParticipants = getParticipantCountWithFake(state)
|
|
||||||
- (iAmRecorder ? 1 : 0)
|
|
||||||
- (disableSelfView ? 1 : 0);
|
|
||||||
const isWeb = navigator.product !== 'ReactNative';
|
|
||||||
|
|
||||||
// When there are 3 participants in the call we want them to be placed on a single row unless the maxColumn setting
|
|
||||||
// is lower.
|
|
||||||
const columnsToMaintainASquare
|
|
||||||
= isWeb && numberOfParticipants === 3 ? 3 : Math.ceil(Math.sqrt(numberOfParticipants));
|
|
||||||
const columns = Math.min(columnsToMaintainASquare, maxColumns);
|
const columns = Math.min(columnsToMaintainASquare, maxColumns);
|
||||||
const rows = Math.ceil(numberOfParticipants / columns);
|
const rows = Math.ceil(numberOfParticipants / columns);
|
||||||
const minVisibleRows = Math.min(maxColumns, rows);
|
const minVisibleRows = Math.min(maxColumns, rows);
|
||||||
|
|
Loading…
Reference in New Issue