feat(tile-view): Optimize grid dimnsions.
This commit is contained in:
parent
f282dbb5dc
commit
bcdccc1dc6
|
@ -74,6 +74,10 @@
|
|||
display: block;
|
||||
}
|
||||
|
||||
.filmstrip__videos.has-scroll {
|
||||
padding-left: 7px;
|
||||
}
|
||||
|
||||
.remote-videos {
|
||||
box-sizing: border-box;
|
||||
|
||||
|
@ -91,7 +95,6 @@
|
|||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
|
||||
.videocontainer {
|
||||
border: 0;
|
||||
|
|
|
@ -211,6 +211,7 @@ export default [
|
|||
'testing',
|
||||
'toolbarButtons',
|
||||
'toolbarConfig',
|
||||
'tileView',
|
||||
'transcribingEnabled',
|
||||
'useHostPageLocalStorage',
|
||||
'useTurnUdp',
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
// @flow
|
||||
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 {
|
||||
|
@ -17,11 +21,14 @@ import {
|
|||
STAGE_VIEW_THUMBNAIL_VERTICAL_BORDER,
|
||||
TILE_HORIZONTAL_MARGIN,
|
||||
TILE_VERTICAL_MARGIN,
|
||||
TILE_VIEW_GRID_HORIZONTAL_MARGIN,
|
||||
TILE_VIEW_GRID_VERTICAL_MARGIN,
|
||||
VERTICAL_FILMSTRIP_VERTICAL_MARGIN
|
||||
} from './constants';
|
||||
import {
|
||||
calculateNotResponsiveTileViewDimensions,
|
||||
calculateResponsiveTileViewDimensions,
|
||||
calculateThumbnailSizeForHorizontalView,
|
||||
calculateThumbnailSizeForTileView,
|
||||
calculateThumbnailSizeForVerticalView
|
||||
} from './functions';
|
||||
|
||||
|
@ -35,37 +42,40 @@ export * from './actions.any';
|
|||
* resolved to Redux state using the {@code toState} function.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function setTileViewDimensions(dimensions: Object) {
|
||||
export function setTileViewDimensions() {
|
||||
return (dispatch: Dispatch<any>, getState: Function) => {
|
||||
const state = getState();
|
||||
const { clientHeight, clientWidth } = state['features/base/responsive-ui'];
|
||||
const { disableResponsiveTiles, disableTileEnlargement } = state['features/base/config'];
|
||||
const { disableResponsiveTiles } = state['features/base/config'];
|
||||
const {
|
||||
height,
|
||||
width
|
||||
} = calculateThumbnailSizeForTileView({
|
||||
...dimensions,
|
||||
clientWidth,
|
||||
clientHeight,
|
||||
disableResponsiveTiles,
|
||||
disableTileEnlargement
|
||||
});
|
||||
const { columns, rows } = dimensions;
|
||||
width,
|
||||
columns,
|
||||
rows
|
||||
} = disableResponsiveTiles
|
||||
? calculateNotResponsiveTileViewDimensions(state)
|
||||
: calculateResponsiveTileViewDimensions(state);
|
||||
const thumbnailsTotalHeight = rows * (TILE_VERTICAL_MARGIN + height);
|
||||
const hasScroll = clientHeight < thumbnailsTotalHeight;
|
||||
const filmstripWidth = (columns * (TILE_HORIZONTAL_MARGIN + width)) + (hasScroll ? SCROLL_SIZE : 0);
|
||||
const filmstripHeight = Math.min(clientHeight, 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);
|
||||
|
||||
dispatch({
|
||||
type: SET_TILE_VIEW_DIMENSIONS,
|
||||
dimensions: {
|
||||
gridDimensions: dimensions,
|
||||
gridDimensions: {
|
||||
columns,
|
||||
rows
|
||||
},
|
||||
thumbnailSize: {
|
||||
height,
|
||||
width
|
||||
},
|
||||
filmstripHeight,
|
||||
filmstripWidth
|
||||
filmstripWidth,
|
||||
hasScroll
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -676,6 +676,7 @@ function _mapStateToProps(state) {
|
|||
gridDimensions = {},
|
||||
filmstripHeight,
|
||||
filmstripWidth,
|
||||
hasScroll = false,
|
||||
thumbnailSize: tileViewThumbnailSize
|
||||
} = state['features/filmstrip'].tileViewDimensions;
|
||||
const _currentLayout = getCurrentLayout(state);
|
||||
|
@ -702,7 +703,7 @@ function _mapStateToProps(state) {
|
|||
const shouldReduceHeight = reduceHeight && (
|
||||
isMobileBrowser() || _currentLayout !== LAYOUTS.VERTICAL_FILMSTRIP_VIEW);
|
||||
|
||||
const videosClassName = `filmstrip__videos${visible ? '' : ' hidden'}`;
|
||||
let videosClassName = `filmstrip__videos${visible ? '' : ' hidden'}`;
|
||||
const className = `${remoteVideosVisible ? '' : 'hide-videos'} ${
|
||||
shouldReduceHeight ? 'reduce-height' : ''
|
||||
} ${shiftRight ? 'shift-right' : ''} ${collapseTileView ? 'collapse' : ''} ${visible ? '' : 'hidden'}`.trim();
|
||||
|
@ -710,6 +711,9 @@ function _mapStateToProps(state) {
|
|||
|
||||
switch (_currentLayout) {
|
||||
case LAYOUTS.TILE_VIEW:
|
||||
if (hasScroll) {
|
||||
videosClassName += ' has-scroll';
|
||||
}
|
||||
_thumbnailSize = tileViewThumbnailSize;
|
||||
remoteFilmstripHeight = filmstripHeight - (collapseTileView && filmstripPadding > 0 ? filmstripPadding : 0);
|
||||
remoteFilmstripWidth = filmstripWidth;
|
||||
|
|
|
@ -28,16 +28,6 @@ export const SQUARE_TILE_ASPECT_RATIO = 1;
|
|||
*/
|
||||
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.
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -142,14 +137,14 @@ export const TILE_HORIZONTAL_MARGIN = 4;
|
|||
*
|
||||
* @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.
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
export const TILE_VIEW_GRID_HORIZONTAL_MARGIN = 12;
|
||||
export const TILE_VIEW_GRID_HORIZONTAL_MARGIN = 14;
|
||||
|
||||
/**
|
||||
* The height of the whole toolbar.
|
||||
|
|
|
@ -9,13 +9,14 @@ import {
|
|||
getPinnedParticipant
|
||||
} from '../base/participants';
|
||||
import { toState } from '../base/redux';
|
||||
import { shouldHideSelfView } from '../base/settings/functions.any';
|
||||
import {
|
||||
getLocalVideoTrack,
|
||||
getTrackByMediaTypeAndParticipant,
|
||||
isLocalTrackMuted,
|
||||
isRemoteTrackMuted
|
||||
} from '../base/tracks/functions';
|
||||
import { LAYOUTS } from '../video-layout';
|
||||
import { getMaxColumnCount, getNotResoinsiveTileViewGridDimensions, LAYOUTS } from '../video-layout';
|
||||
|
||||
import {
|
||||
ASPECT_RATIO_BREAKPOINT,
|
||||
|
@ -23,7 +24,6 @@ import {
|
|||
DISPLAY_VIDEO,
|
||||
INDICATORS_TOOLTIP_POSITION,
|
||||
SCROLL_SIZE,
|
||||
SQUARE_TILE_ASPECT_RATIO,
|
||||
STAGE_VIEW_THUMBNAIL_HORIZONTAL_BORDER,
|
||||
TILE_ASPECT_RATIO,
|
||||
TILE_HORIZONTAL_MARGIN,
|
||||
|
@ -33,7 +33,9 @@ import {
|
|||
VERTICAL_FILMSTRIP_MIN_HORIZONTAL_MARGIN,
|
||||
TILE_MIN_HEIGHT_LARGE,
|
||||
TILE_MIN_HEIGHT_SMALL,
|
||||
TILE_PORTRAIT_ASPECT_RATIO
|
||||
TILE_PORTRAIT_ASPECT_RATIO,
|
||||
SQUARE_TILE_ASPECT_RATIO,
|
||||
TILE_VIEW_DEFAULT_NUMBER_OF_VISIBLE_TILES
|
||||
} from './constants';
|
||||
|
||||
export * from './functions.any';
|
||||
|
@ -174,6 +176,202 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 } = getNotResoinsiveTileViewGridDimensions(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(state) {
|
||||
const { clientHeight, clientWidth } = state['features/base/responsive-ui'];
|
||||
const {
|
||||
disableTileEnlargement,
|
||||
iAmRecorder,
|
||||
tileView = {}
|
||||
} = state['features/base/config'];
|
||||
const { numberOfVisibleTiles = TILE_VIEW_DEFAULT_NUMBER_OF_VISIBLE_TILES } = tileView;
|
||||
|
||||
let height, width;
|
||||
let columns, rows;
|
||||
|
||||
// When in tile view mode, we must discount ourselves (the local participant) because our
|
||||
// tile is not visible.
|
||||
const disableSelfView = shouldHideSelfView(state);
|
||||
const numberOfParticipants = getParticipantCountWithFake(state)
|
||||
- (iAmRecorder ? 1 : 0)
|
||||
- (disableSelfView ? 1 : 0);
|
||||
|
||||
let dimensions = {
|
||||
maxArea: 0
|
||||
};
|
||||
let minHeightEnforcedDimensions = {
|
||||
maxArea: 0
|
||||
};
|
||||
let zeroVisibleRowsDimensions = {
|
||||
maxArea: 0
|
||||
};
|
||||
const maxColumns = getMaxColumnCount(state);
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
// 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.
|
||||
*
|
||||
|
@ -183,88 +381,76 @@ export function calculateThumbnailSizeForVerticalView(clientWidth: number = 0) {
|
|||
export function calculateThumbnailSizeForTileView({
|
||||
columns,
|
||||
minVisibleRows,
|
||||
rows,
|
||||
clientWidth,
|
||||
clientHeight,
|
||||
disableResponsiveTiles,
|
||||
disableTileEnlargement
|
||||
disableResponsiveTiles = false,
|
||||
disableTileEnlargement = false
|
||||
}: Object) {
|
||||
let aspectRatio = TILE_ASPECT_RATIO;
|
||||
|
||||
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 aspectRatio = getTileDefaultAspectRatio(disableResponsiveTiles, disableTileEnlargement, clientWidth);
|
||||
const minHeight = getThumbnailMinHeight(clientWidth);
|
||||
const viewWidth = clientWidth - (columns * TILE_HORIZONTAL_MARGIN) - TILE_VIEW_GRID_HORIZONTAL_MARGIN;
|
||||
const viewHeight = clientHeight - (minVisibleRows * TILE_VERTICAL_MARGIN) - TILE_VIEW_GRID_VERTICAL_MARGIN;
|
||||
const initialWidth = viewWidth / columns;
|
||||
const initialHeight = viewHeight / minVisibleRows;
|
||||
const aspectRatioHeight = initialWidth / aspectRatio;
|
||||
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);
|
||||
let initialHeight = viewHeight / minVisibleRows;
|
||||
let minHeightEnforced = false;
|
||||
|
||||
if (height > noScrollHeight && width > scrollInitialWidth) { // we will have scroll and we need more space for it.
|
||||
const scrollAspectRatioHeight = scrollInitialWidth / aspectRatio;
|
||||
|
||||
// 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 (initialHeight < minHeight) {
|
||||
minHeightEnforced = true;
|
||||
initialHeight = minHeight;
|
||||
}
|
||||
|
||||
if (disableTileEnlargement) {
|
||||
return {
|
||||
height,
|
||||
width
|
||||
};
|
||||
}
|
||||
const aspectRatioHeight = initialWidth / aspectRatio;
|
||||
|
||||
if (initialHeight > noScrollHeight) {
|
||||
height = Math.max(height, viewHeight / rows, minHeight);
|
||||
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
|
||||
};
|
||||
if (aspectRatioHeight < minHeight) { // we can't fit the required number of columns.
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
height: Math.min(height, heightFromWidth),
|
||||
width
|
||||
};
|
||||
} else if (height < width) {
|
||||
const height = Math.floor(Math.min(aspectRatioHeight, initialHeight));
|
||||
|
||||
return {
|
||||
height,
|
||||
width: Math.min(width, aspectRatio * height)
|
||||
width: Math.floor(aspectRatio * height),
|
||||
minHeightEnforced,
|
||||
maxVisibleRows: Math.floor(viewHeight / height)
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
height,
|
||||
width
|
||||
};
|
||||
const initialRatio = initialWidth / initialHeight;
|
||||
let height = Math.floor(initialHeight);
|
||||
|
||||
// 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.
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,9 +40,7 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
|
||||
switch (layout) {
|
||||
case LAYOUTS.TILE_VIEW: {
|
||||
const { gridDimensions } = state['features/filmstrip'].tileViewDimensions;
|
||||
|
||||
store.dispatch(setTileViewDimensions(gridDimensions));
|
||||
store.dispatch(setTileViewDimensions());
|
||||
break;
|
||||
}
|
||||
case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { getParticipantCountWithFake } from '../base/participants';
|
||||
import { StateListenerRegistry } from '../base/redux';
|
||||
import { getTileViewGridDimensions, shouldDisplayTileView } from '../video-layout';
|
||||
import { shouldDisplayTileView } from '../video-layout';
|
||||
|
||||
import { setTileViewDimensions } from './actions';
|
||||
import './subscriber.any';
|
||||
|
@ -34,9 +34,7 @@ StateListenerRegistry.register(
|
|||
StateListenerRegistry.register(
|
||||
/* selector */ state => shouldDisplayTileView(state),
|
||||
/* listener */ (isTileView, store) => {
|
||||
const state = store.getState();
|
||||
|
||||
if (isTileView) {
|
||||
store.dispatch(setTileViewDimensions(getTileViewGridDimensions(state)));
|
||||
store.dispatch(setTileViewDimensions());
|
||||
}
|
||||
});
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
import { isMobileBrowser } from '../base/environment/utils';
|
||||
import { getParticipantCountWithFake } from '../base/participants';
|
||||
import { StateListenerRegistry, equals } from '../base/redux';
|
||||
import { StateListenerRegistry } from '../base/redux';
|
||||
import { clientResized } from '../base/responsive-ui';
|
||||
import { shouldHideSelfView } from '../base/settings';
|
||||
import { setFilmstripVisible } from '../filmstrip/actions';
|
||||
import { getParticipantsPaneOpen } from '../participants-pane/functions';
|
||||
import { setOverflowDrawer } from '../toolbox/actions.web';
|
||||
import { getCurrentLayout, getTileViewGridDimensions, shouldDisplayTileView, LAYOUTS } from '../video-layout';
|
||||
import { getCurrentLayout, shouldDisplayTileView, LAYOUTS } from '../video-layout';
|
||||
|
||||
import {
|
||||
setHorizontalViewDimensions,
|
||||
|
@ -17,9 +17,7 @@ import {
|
|||
} from './actions';
|
||||
import {
|
||||
ASPECT_RATIO_BREAKPOINT,
|
||||
DISPLAY_DRAWER_THRESHOLD,
|
||||
SINGLE_COLUMN_BREAKPOINT,
|
||||
TWO_COLUMN_BREAKPOINT
|
||||
DISPLAY_DRAWER_THRESHOLD
|
||||
} from './constants';
|
||||
import './subscriber.any';
|
||||
|
||||
|
@ -38,12 +36,7 @@ StateListenerRegistry.register(
|
|||
const state = store.getState();
|
||||
|
||||
if (shouldDisplayTileView(state)) {
|
||||
const gridDimensions = getTileViewGridDimensions(state);
|
||||
const oldGridDimensions = state['features/filmstrip'].tileViewDimensions.gridDimensions;
|
||||
|
||||
if (!equals(gridDimensions, oldGridDimensions)) {
|
||||
store.dispatch(setTileViewDimensions(gridDimensions));
|
||||
}
|
||||
store.dispatch(setTileViewDimensions());
|
||||
}
|
||||
}, {
|
||||
deepEquals: true
|
||||
|
@ -55,11 +48,9 @@ StateListenerRegistry.register(
|
|||
StateListenerRegistry.register(
|
||||
/* selector */ state => getCurrentLayout(state),
|
||||
/* listener */ (layout, store) => {
|
||||
const state = store.getState();
|
||||
|
||||
switch (layout) {
|
||||
case LAYOUTS.TILE_VIEW:
|
||||
store.dispatch(setTileViewDimensions(getTileViewGridDimensions(state)));
|
||||
store.dispatch(setTileViewDimensions());
|
||||
break;
|
||||
case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW:
|
||||
store.dispatch(setHorizontalViewDimensions());
|
||||
|
@ -126,47 +117,3 @@ StateListenerRegistry.register(
|
|||
store.dispatch(setFilmstripVisible(!widthBelowThreshold));
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -10,11 +10,8 @@ import {
|
|||
} from '../base/participants';
|
||||
import { shouldHideSelfView } from '../base/settings/functions.any';
|
||||
import {
|
||||
ASPECT_RATIO_BREAKPOINT,
|
||||
DEFAULT_MAX_COLUMNS,
|
||||
ABSOLUTE_MAX_COLUMNS,
|
||||
SINGLE_COLUMN_BREAKPOINT,
|
||||
TWO_COLUMN_BREAKPOINT
|
||||
ABSOLUTE_MAX_COLUMNS
|
||||
} from '../filmstrip/constants';
|
||||
import { isVideoPlaying } from '../shared-video/functions';
|
||||
|
||||
|
@ -61,31 +58,10 @@ export function getCurrentLayout(state: Object) {
|
|||
* @param {Object} state - The redux store state.
|
||||
* @returns {number}
|
||||
*/
|
||||
export function getMaxColumnCount(state: Object) {
|
||||
export function getMaxColumnCount() {
|
||||
const configuredMax = (typeof interfaceConfig === 'undefined'
|
||||
? 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 participantCount = getParticipantCount(state);
|
||||
|
||||
// If there are just two participants in a conference, enforce single-column view for mobile size.
|
||||
if (participantCount === 2 && clientWidth < ASPECT_RATIO_BREAKPOINT) {
|
||||
return Math.min(1, Math.max(configuredMax, 1));
|
||||
}
|
||||
|
||||
// Enforce single column view at very small screen widths.
|
||||
if (clientWidth < SINGLE_COLUMN_BREAKPOINT) {
|
||||
return Math.min(1, Math.max(configuredMax, 1));
|
||||
}
|
||||
|
||||
// Enforce two column view below breakpoint.
|
||||
if (clientWidth < TWO_COLUMN_BREAKPOINT) {
|
||||
return Math.min(2, Math.max(configuredMax, 1));
|
||||
}
|
||||
}
|
||||
|
||||
return Math.min(Math.max(configuredMax, 1), ABSOLUTE_MAX_COLUMNS);
|
||||
}
|
||||
|
@ -99,7 +75,7 @@ export function getMaxColumnCount(state: Object) {
|
|||
* @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.
|
||||
*/
|
||||
export function getTileViewGridDimensions(state: Object) {
|
||||
export function getNotResoinsiveTileViewGridDimensions(state: Object) {
|
||||
const maxColumns = getMaxColumnCount(state);
|
||||
|
||||
// When in tile view mode, we must discount ourselves (the local participant) because our
|
||||
|
@ -109,12 +85,7 @@ export function getTileViewGridDimensions(state: Object) {
|
|||
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 columnsToMaintainASquare = Math.ceil(Math.sqrt(numberOfParticipants));
|
||||
const columns = Math.min(columnsToMaintainASquare, maxColumns);
|
||||
const rows = Math.ceil(numberOfParticipants / columns);
|
||||
const minVisibleRows = Math.min(maxColumns, rows);
|
||||
|
|
Loading…
Reference in New Issue