feat(tile-vew): Calculate maxColumns dynamically

This commit is contained in:
Hristo Terezov 2022-03-25 10:40:46 -05:00
parent 744607a5cc
commit 221ecac12d
3 changed files with 108 additions and 51 deletions

View File

@ -83,14 +83,15 @@ export function setTileViewDimensions() {
disableTileEnlargement,
maxColumns,
numberOfParticipants,
numberOfVisibleTiles
desiredNumberOfVisibleTiles: numberOfVisibleTiles
});
const thumbnailsTotalHeight = rows * (TILE_VERTICAL_MARGIN + height);
const hasScroll = clientHeight < thumbnailsTotalHeight;
const availableHeight = clientHeight - TILE_VIEW_GRID_VERTICAL_MARGIN;
const hasScroll = availableHeight < thumbnailsTotalHeight;
const filmstripWidth
= 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);
const filmstripHeight = Math.min(availableHeight, thumbnailsTotalHeight);
dispatch({
type: SET_TILE_VIEW_DIMENSIONS,
@ -139,7 +140,11 @@ export function setVerticalViewDimensions() {
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 maxColumns = getMaxColumnCount(state, {
width: filmstripWidth.current,
disableResponsiveTiles: false,
disableTileEnlargement: false
});
const {
height,
width,
@ -152,7 +157,7 @@ export function setVerticalViewDimensions() {
maxColumns,
noHorizontalContainerMargin: true,
numberOfParticipants,
numberOfVisibleTiles
desiredNumberOfVisibleTiles: numberOfVisibleTiles
});
const thumbnailsTotalHeight = rows * (TILE_VERTICAL_MARGIN + height);
@ -269,7 +274,8 @@ export function setStageFilmstripViewDimensions() {
const verticalWidth = visible ? getVerticalViewMaxWidth(state) : 0;
const { numberOfVisibleTiles = MAX_ACTIVE_PARTICIPANTS } = tileView;
const numberOfParticipants = state['features/filmstrip'].activeParticipants.length;
const maxColumns = getMaxColumnCount(state);
const availableWidth = clientWidth - verticalWidth;
const maxColumns = getMaxColumnCount(state, { width: availableWidth });
const {
height,
@ -279,7 +285,7 @@ export function setStageFilmstripViewDimensions() {
} = disableResponsiveTiles
? calculateNonResponsiveTileViewDimensions(state, true)
: calculateResponsiveTileViewDimensions({
clientWidth: clientWidth - verticalWidth,
clientWidth: availableWidth,
clientHeight,
disableTileEnlargement,
maxColumns,

View File

@ -297,7 +297,7 @@ export function calculateResponsiveTileViewDimensions({
noHorizontalContainerMargin = false,
maxColumns,
numberOfParticipants,
numberOfVisibleTiles = TILE_VIEW_DEFAULT_NUMBER_OF_VISIBLE_TILES
desiredNumberOfVisibleTiles = TILE_VIEW_DEFAULT_NUMBER_OF_VISIBLE_TILES
}) {
let height, width;
let columns, rows;
@ -311,12 +311,12 @@ export function calculateResponsiveTileViewDimensions({
maxArea: 0
};
for (let c = 1; c <= Math.min(maxColumns, numberOfParticipants); c++) {
for (let c = 1; c <= Math.min(maxColumns, numberOfParticipants, desiredNumberOfVisibleTiles); c++) {
const r = Math.ceil(numberOfParticipants / c);
// we want to display as much as possible tumbnails up to numberOfVisibleTiles
// we want to display as much as possible tumbnails up to desiredNumberOfVisibleTiles
const visibleRows
= numberOfParticipants <= numberOfVisibleTiles ? r : Math.floor(numberOfVisibleTiles / c);
= numberOfParticipants <= desiredNumberOfVisibleTiles ? r : Math.floor(desiredNumberOfVisibleTiles / c);
const size = calculateThumbnailSizeForTileView({
columns: c,
@ -330,18 +330,38 @@ export function calculateResponsiveTileViewDimensions({
if (size) {
const { height: currentHeight, width: currentWidth, minHeightEnforced, maxVisibleRows } = size;
let area = currentHeight * currentWidth * Math.min(c * maxVisibleRows, numberOfParticipants);
const numberOfVisibleParticipants = Math.min(c * maxVisibleRows, numberOfParticipants);
let area = Math.round(
(currentHeight + TILE_VERTICAL_MARGIN)
* (currentWidth + TILE_HORIZONTAL_MARGIN)
* numberOfVisibleParticipants);
const currentDimensions = {
maxArea: area,
height: currentHeight,
width: currentWidth,
columns: c,
rows: r
rows: r,
numberOfVisibleParticipants
};
const { numberOfVisibleParticipants: oldNumberOfVisibleParticipants = 0 } = dimensions;
if (!minHeightEnforced && area > dimensions.maxArea) {
if (!minHeightEnforced) {
if (area > dimensions.maxArea) {
dimensions = currentDimensions;
} else if (minHeightEnforced && area > minHeightEnforcedDimensions.maxArea) {
} else if ((area === dimensions.maxArea)
&& ((oldNumberOfVisibleParticipants > desiredNumberOfVisibleTiles
&& oldNumberOfVisibleParticipants >= numberOfParticipants)
|| (oldNumberOfVisibleParticipants < numberOfParticipants
&& numberOfVisibleParticipants <= desiredNumberOfVisibleTiles))
) { // If the area of the new candidates and the old ones are equal we preffer the one that will have
// closer number of visible participants to desiredNumberOfVisibleTiles config.
dimensions = currentDimensions;
}
} else if (minHeightEnforced && area >= minHeightEnforcedDimensions.maxArea) {
// If we choose configuration with minHeightEnforced there will be less than desiredNumberOfVisibleTiles
// visible tiles, that's why we prefer more columns when the area is the same.
minHeightEnforcedDimensions = currentDimensions;
} else if (minHeightEnforced && maxVisibleRows === 0) {
area = currentHeight * currentWidth * Math.min(c, numberOfParticipants);
@ -400,7 +420,8 @@ export function calculateThumbnailSizeForTileView({
const minHeight = getThumbnailMinHeight(clientWidth);
const viewWidth = clientWidth - (columns * TILE_HORIZONTAL_MARGIN)
- (noHorizontalContainerMargin ? SCROLL_SIZE : TILE_VIEW_GRID_HORIZONTAL_MARGIN);
const viewHeight = clientHeight - (minVisibleRows * TILE_VERTICAL_MARGIN) - TILE_VIEW_GRID_VERTICAL_MARGIN;
const availableHeight = clientHeight - TILE_VIEW_GRID_VERTICAL_MARGIN;
const viewHeight = availableHeight - (minVisibleRows * TILE_VERTICAL_MARGIN);
const initialWidth = viewWidth / columns;
let initialHeight = viewHeight / minVisibleRows;
let minHeightEnforced = false;
@ -417,54 +438,49 @@ export function calculateThumbnailSizeForTileView({
return;
}
const height = Math.floor(Math.min(aspectRatioHeight, initialHeight));
const height = Math.min(aspectRatioHeight, initialHeight);
return {
height,
width: Math.floor(aspectRatio * height),
width: aspectRatio * height,
minHeightEnforced,
maxVisibleRows: Math.floor(viewHeight / height)
maxVisibleRows: Math.floor(availableHeight / (height + TILE_VERTICAL_MARGIN))
};
}
const initialRatio = initialWidth / initialHeight;
let height = Math.floor(initialHeight);
let height = initialHeight;
let 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)
};
width = initialHeight * aspectRatio;
} else if (initialRatio >= TILE_PORTRAIT_ASPECT_RATIO) {
return {
height,
width: Math.floor(initialWidth),
minHeightEnforced,
maxVisibleRows: Math.floor(viewHeight / height)
};
width = initialWidth;
// eslint-disable-next-line no-negated-condition
} else if (!minHeightEnforced) {
height = Math.floor(initialWidth / TILE_PORTRAIT_ASPECT_RATIO);
height = initialWidth / TILE_PORTRAIT_ASPECT_RATIO;
if (height >= minHeight) {
return {
height,
width: Math.floor(initialWidth),
minHeightEnforced,
maxVisibleRows: Math.floor(viewHeight / height)
};
width = initialWidth;
} else { // The width is so small that we can't reach the minimum height with portrait aspect ratio.
return;
}
}
// else
} else {
// We can't fit that number of columns with the desired min height and aspect ratio.
return;
}
return {
height,
width,
minHeightEnforced,
maxVisibleRows: Math.floor(availableHeight / (height + TILE_VERTICAL_MARGIN))
};
}
/**
* Returns the width of the visible area (doesn't include the left margin/padding) of the the vertical filmstrip.
*

View File

@ -9,9 +9,14 @@ import {
} from '../base/participants';
import {
DEFAULT_MAX_COLUMNS,
ABSOLUTE_MAX_COLUMNS
ABSOLUTE_MAX_COLUMNS,
TILE_PORTRAIT_ASPECT_RATIO
} from '../filmstrip/constants';
import { getNumberOfPartipantsForTileView } from '../filmstrip/functions.web';
import {
getNumberOfPartipantsForTileView,
getThumbnailMinHeight,
getTileDefaultAspectRatio
} from '../filmstrip/functions.web';
import { isVideoPlaying } from '../shared-video/functions';
import { VIDEO_QUALITY_LEVELS } from '../video-quality/constants';
@ -56,15 +61,45 @@ export function getCurrentLayout(state: Object) {
* returned will be between 1 and 7, inclusive.
*
* @param {Object} state - The redux store state.
* @param {number} width - Custom width to use for calculation.
* @param {Object} options - Object with custom values used to override the values that we get from redux by default.
* @param {number} options.width - Custom width to be used.
* @param {boolean} options.disableResponsiveTiles - Custom value to be used instead of config.disableResponsiveTiles.
* @param {boolean} options.disableTileEnlargement - Custom value to be used instead of config.disableTileEnlargement.
* @returns {number}
*/
export function getMaxColumnCount() {
const configuredMax = (typeof interfaceConfig === 'undefined'
? DEFAULT_MAX_COLUMNS
: interfaceConfig.TILE_VIEW_MAX_COLUMNS) || DEFAULT_MAX_COLUMNS;
export function getMaxColumnCount(state, options = {}) {
if (typeof interfaceConfig === 'undefined') {
return DEFAULT_MAX_COLUMNS;
}
return Math.min(Math.max(configuredMax, 1), ABSOLUTE_MAX_COLUMNS);
const {
disableResponsiveTiles: configDisableResponsiveTiles,
disableTileEnlargement: configDisableTileEnlargement
} = state['features/base/config'];
const {
width,
disableResponsiveTiles = configDisableResponsiveTiles,
disableTileEnlargement = configDisableTileEnlargement
} = options;
const { clientWidth } = state['features/base/responsive-ui'];
const widthToUse = width || clientWidth;
const configuredMax = interfaceConfig.TILE_VIEW_MAX_COLUMNS;
if (disableResponsiveTiles) {
return Math.min(Math.max(configuredMax || DEFAULT_MAX_COLUMNS, 1), ABSOLUTE_MAX_COLUMNS);
}
if (typeof interfaceConfig.TILE_VIEW_MAX_COLUMNS !== 'undefined' && interfaceConfig.TILE_VIEW_MAX_COLUMNS > 0) {
return Math.max(configuredMax, 1);
}
const aspectRatio = disableTileEnlargement
? getTileDefaultAspectRatio(true, disableTileEnlargement, widthToUse)
: TILE_PORTRAIT_ASPECT_RATIO;
const minHeight = getThumbnailMinHeight(widthToUse);
const minWidth = aspectRatio * minHeight;
return Math.floor(widthToUse / minWidth);
}
/**