feat(tiles): Add responsive behaviour.
* Enforce fixed column number at various width breakpoints. * Bring back the filmstrip at small sizes but hide it. * Change default maximum columns to 7.
This commit is contained in:
parent
6ca3c6e43a
commit
db84889143
|
@ -143,16 +143,6 @@
|
|||
|
||||
@media only screen and (max-width: $verySmallScreen) {
|
||||
@include very-small-button-size();
|
||||
|
||||
#videoResolutionLabel {
|
||||
display: none;
|
||||
}
|
||||
.vertical-filmstrip .filmstrip {
|
||||
display: none;
|
||||
}
|
||||
.chrome-extension-banner {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.shift-right {
|
||||
|
|
|
@ -100,6 +100,15 @@
|
|||
video {
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Max-width corresponding to the ASPECT_RATIO_BREAKPOINT from features/filmstrip/constants.
|
||||
*/
|
||||
@media only screen and (max-width: 500px) {
|
||||
video {
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.has-overflow#filmstripRemoteVideosContainer {
|
||||
|
|
|
@ -10,7 +10,40 @@ export const FILMSTRIP_SIZE = 90;
|
|||
*/
|
||||
export const TILE_ASPECT_RATIO = 16 / 9;
|
||||
|
||||
/**
|
||||
* The aspect ratio of a square tile in tile view.
|
||||
*/
|
||||
export const SQUARE_TILE_ASPECT_RATIO = 1;
|
||||
|
||||
/**
|
||||
* Width below which the overflow menu(s) will be displayed as drawer(s).
|
||||
*/
|
||||
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
|
||||
* single column view.
|
||||
* If this is to be modified, please also change the related media query from the tile_view scss file.
|
||||
*/
|
||||
export const ASPECT_RATIO_BREAKPOINT = 500;
|
||||
|
||||
/**
|
||||
* The default number of columns for tile view.
|
||||
*/
|
||||
export const DEFAULT_MAX_COLUMNS = 5;
|
||||
|
||||
/**
|
||||
* An extended number of columns for tile view.
|
||||
*/
|
||||
export const ABSOLUTE_MAX_COLUMNS = 7;
|
||||
|
|
|
@ -16,7 +16,7 @@ import {
|
|||
isRemoteTrackMuted
|
||||
} from '../base/tracks/functions';
|
||||
|
||||
import { TILE_ASPECT_RATIO } from './constants';
|
||||
import { ASPECT_RATIO_BREAKPOINT, SQUARE_TILE_ASPECT_RATIO, TILE_ASPECT_RATIO } from './constants';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
|
@ -142,12 +142,13 @@ export function calculateThumbnailSizeForTileView({
|
|||
clientWidth,
|
||||
clientHeight
|
||||
}: Object) {
|
||||
const aspectRatio = clientWidth < ASPECT_RATIO_BREAKPOINT ? SQUARE_TILE_ASPECT_RATIO : TILE_ASPECT_RATIO;
|
||||
const viewWidth = clientWidth - TILE_VIEW_SIDE_MARGINS;
|
||||
const viewHeight = clientHeight - TILE_VIEW_SIDE_MARGINS;
|
||||
const initialWidth = viewWidth / columns;
|
||||
const aspectRatioHeight = initialWidth / TILE_ASPECT_RATIO;
|
||||
const aspectRatioHeight = initialWidth / aspectRatio;
|
||||
const height = Math.floor(Math.min(aspectRatioHeight, viewHeight / visibleRows));
|
||||
const width = Math.floor(TILE_ASPECT_RATIO * height);
|
||||
const width = Math.floor(aspectRatio * height);
|
||||
|
||||
return {
|
||||
height,
|
||||
|
|
|
@ -3,11 +3,17 @@
|
|||
import Filmstrip from '../../../modules/UI/videolayout/Filmstrip';
|
||||
import VideoLayout from '../../../modules/UI/videolayout/VideoLayout';
|
||||
import { StateListenerRegistry, equals } from '../base/redux';
|
||||
import { setFilmstripVisible } from '../filmstrip/actions';
|
||||
import { setOverflowDrawer } from '../toolbox/actions.web';
|
||||
import { getCurrentLayout, getTileViewGridDimensions, shouldDisplayTileView, LAYOUTS } from '../video-layout';
|
||||
|
||||
import { setHorizontalViewDimensions, setTileViewDimensions } from './actions.web';
|
||||
import { DISPLAY_DRAWER_THRESHOLD } from './constants';
|
||||
import {
|
||||
ASPECT_RATIO_BREAKPOINT,
|
||||
DISPLAY_DRAWER_THRESHOLD,
|
||||
SINGLE_COLUMN_BREAKPOINT,
|
||||
TWO_COLUMN_BREAKPOINT
|
||||
} from './constants';
|
||||
|
||||
/**
|
||||
* Listens for changes in the number of participants to calculate the dimensions of the tile view grid and the tiles.
|
||||
|
@ -134,3 +140,67 @@ StateListenerRegistry.register(
|
|||
/* listener */ (widthBelowThreshold, store) => {
|
||||
store.dispatch(setOverflowDrawer(widthBelowThreshold));
|
||||
});
|
||||
|
||||
/**
|
||||
* Gracefully hide/show the filmstrip when going past threshold.
|
||||
*/
|
||||
StateListenerRegistry.register(
|
||||
/* selector */ state => state['features/base/responsive-ui'].clientWidth < ASPECT_RATIO_BREAKPOINT,
|
||||
/* listener */ (widthBelowThreshold, store) => {
|
||||
store.dispatch(setFilmstripVisible(!widthBelowThreshold));
|
||||
});
|
||||
|
||||
/**
|
||||
* Symbol mapping used for the tile view responsiveness computation.
|
||||
*/
|
||||
const responsiveColumnMapping = {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* This gets called either when the width of the screen is above {@code TWO_COLUMN_BREAKPOINT}
|
||||
* or below {@CODE SINGLE_COLUMN_BREAKPOINT}, however, the internal logic from {@code getMaxColumnCount}
|
||||
* only takes the second case into consideration.
|
||||
*/
|
||||
return responsiveColumnMapping.singleColumn;
|
||||
},
|
||||
/* listener */ (_, store) => {
|
||||
const state = store.getState();
|
||||
|
||||
if (shouldDisplayTileView(state)) {
|
||||
const gridDimensions = getTileViewGridDimensions(state);
|
||||
const { clientHeight, clientWidth } = state['features/base/responsive-ui'];
|
||||
const { isOpen } = state['features/chat'];
|
||||
|
||||
store.dispatch(
|
||||
setTileViewDimensions(
|
||||
gridDimensions,
|
||||
{
|
||||
clientHeight,
|
||||
clientWidth
|
||||
},
|
||||
isOpen
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -2,6 +2,14 @@
|
|||
|
||||
import { getFeatureFlag, TILE_VIEW_ENABLED } from '../base/flags';
|
||||
import { getPinnedParticipant, getParticipantCount } from '../base/participants';
|
||||
import { CHAT_SIZE } from '../chat/constants';
|
||||
import {
|
||||
ASPECT_RATIO_BREAKPOINT,
|
||||
DEFAULT_MAX_COLUMNS,
|
||||
ABSOLUTE_MAX_COLUMNS,
|
||||
SINGLE_COLUMN_BREAKPOINT,
|
||||
TWO_COLUMN_BREAKPOINT
|
||||
} from '../filmstrip/constants';
|
||||
import { isYoutubeVideoPlaying } from '../youtube-player/functions';
|
||||
|
||||
import { LAYOUTS } from './constants';
|
||||
|
@ -27,14 +35,38 @@ export function getCurrentLayout(state: Object) {
|
|||
|
||||
/**
|
||||
* Returns how many columns should be displayed in tile view. The number
|
||||
* returned will be between 1 and 5, inclusive.
|
||||
* returned will be between 1 and 7, inclusive.
|
||||
*
|
||||
* @param {Object} state - The redux store state.
|
||||
* @returns {number}
|
||||
*/
|
||||
export function getMaxColumnCount() {
|
||||
const configuredMax = interfaceConfig.TILE_VIEW_MAX_COLUMNS || 5;
|
||||
export function getMaxColumnCount(state: Object) {
|
||||
const configuredMax = interfaceConfig.TILE_VIEW_MAX_COLUMNS || DEFAULT_MAX_COLUMNS;
|
||||
const { clientWidth } = state['features/base/responsive-ui'];
|
||||
let availableWidth = clientWidth;
|
||||
const participantCount = getParticipantCount(state);
|
||||
const { isOpen } = state['features/chat'];
|
||||
|
||||
return Math.min(Math.max(configuredMax, 1), 5);
|
||||
if (isOpen) {
|
||||
availableWidth -= CHAT_SIZE;
|
||||
}
|
||||
|
||||
// If there are just two participants in a conference, enforce single-column view for mobile size.
|
||||
if (participantCount === 2 && availableWidth < ASPECT_RATIO_BREAKPOINT) {
|
||||
return Math.min(1, Math.max(configuredMax, 1));
|
||||
}
|
||||
|
||||
// Enforce single column view at very small screen widths.
|
||||
if (availableWidth < SINGLE_COLUMN_BREAKPOINT) {
|
||||
return Math.min(1, Math.max(configuredMax, 1));
|
||||
}
|
||||
|
||||
// Enforce two column view below breakpoint.
|
||||
if (availableWidth < TWO_COLUMN_BREAKPOINT) {
|
||||
return Math.min(2, Math.max(configuredMax, 1));
|
||||
}
|
||||
|
||||
return Math.min(Math.max(configuredMax, 1), ABSOLUTE_MAX_COLUMNS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,7 +80,9 @@ export function getMaxColumnCount() {
|
|||
* @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, maxColumns: number = getMaxColumnCount()) {
|
||||
export function getTileViewGridDimensions(state: Object) {
|
||||
const maxColumns = getMaxColumnCount(state);
|
||||
|
||||
// When in tile view mode, we must discount ourselves (the local participant) because our
|
||||
// tile is not visible.
|
||||
const { iAmRecorder } = state['features/base/config'];
|
||||
|
|
Loading…
Reference in New Issue