ref(stage-filmstrip) Refactor as new layout
Fixes screensharing selection issues. Now when there’s a screen share we just use the old VERTICAL_FILMSTRIP_VIEW layout Add THUMBAIL_TYPE to determine how to display thumbnails
This commit is contained in:
parent
dde8c586da
commit
0abefa87aa
|
@ -1,175 +1,177 @@
|
|||
.vertical-filmstrip span:not(.tile-view) .filmstrip {
|
||||
&.hide-videos {
|
||||
.remote-videos {
|
||||
& > div {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
.vertical-filmstrip, .stage-filmstrip {
|
||||
span:not(.tile-view) .filmstrip {
|
||||
&.hide-videos {
|
||||
.remote-videos {
|
||||
& > div {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Firefox sets flex items to min-height: auto and min-width: auto,
|
||||
* preventing flex children from shrinking like they do on other browsers.
|
||||
* Setting min-height and min-width 0 is a workaround for the issue so
|
||||
* Firefox behaves like other browsers.
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=1043520
|
||||
*/
|
||||
@mixin minHWAutoFix() {
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
/*
|
||||
* Firefox sets flex items to min-height: auto and min-width: auto,
|
||||
* preventing flex children from shrinking like they do on other browsers.
|
||||
* Setting min-height and min-width 0 is a workaround for the issue so
|
||||
* Firefox behaves like other browsers.
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=1043520
|
||||
*/
|
||||
@mixin minHWAutoFix() {
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@extend %align-right;
|
||||
align-items: flex-end;
|
||||
bottom: 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
/**
|
||||
* fixed positioning is necessary for remote menus and tooltips to pop
|
||||
* out of the scrolling filmstrip. AtlasKit dialogs and tooltips use
|
||||
* a library called popper which will position its elements fixed if
|
||||
* any parent is also fixed.
|
||||
*/
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: $filmstripVideosZ;
|
||||
|
||||
&.no-vertical-padding {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide videos by making them slight to the right.
|
||||
*/
|
||||
.filmstrip__videos {
|
||||
@extend %align-right;
|
||||
align-items: flex-end;
|
||||
bottom: 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
position:relative;
|
||||
/**
|
||||
* fixed positioning is necessary for remote menus and tooltips to pop
|
||||
* out of the scrolling filmstrip. AtlasKit dialogs and tooltips use
|
||||
* a library called popper which will position its elements fixed if
|
||||
* any parent is also fixed.
|
||||
*/
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: auto;
|
||||
z-index: $filmstripVideosZ;
|
||||
|
||||
&.no-vertical-padding {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* An id selector is used to match id specificity with existing
|
||||
* filmstrip styles.
|
||||
* Hide videos by making them slight to the right.
|
||||
*/
|
||||
&#remoteVideos {
|
||||
border: $thumbnailsBorder solid transparent;
|
||||
padding-left: 0;
|
||||
border-left: 0;
|
||||
.filmstrip__videos {
|
||||
@extend %align-right;
|
||||
bottom: 0;
|
||||
padding: 0;
|
||||
position:relative;
|
||||
right: 0;
|
||||
width: auto;
|
||||
|
||||
/**
|
||||
* An id selector is used to match id specificity with existing
|
||||
* filmstrip styles.
|
||||
*/
|
||||
&#remoteVideos {
|
||||
border: $thumbnailsBorder solid transparent;
|
||||
padding-left: 0;
|
||||
border-left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-styles the local Video to better fit vertical filmstrip layout.
|
||||
*/
|
||||
#filmstripLocalVideo {
|
||||
align-self: initial;
|
||||
margin-bottom: 5px;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
height: auto;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-styles the local Video to better fit vertical filmstrip layout.
|
||||
*/
|
||||
#filmstripLocalVideo {
|
||||
align-self: initial;
|
||||
margin-bottom: 5px;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
height: auto;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
#filmstripLocalVideoThumbnail {
|
||||
width: calc(100% - 15px);
|
||||
|
||||
#filmstripLocalVideoThumbnail {
|
||||
width: calc(100% - 15px);
|
||||
|
||||
.videocontainer {
|
||||
height: 0px;
|
||||
width: 100%;
|
||||
.videocontainer {
|
||||
height: 0px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#filmstripLocalScreenShare {
|
||||
align-self: initial;
|
||||
margin-bottom: 5px;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
height: auto;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
#filmstripLocalScreenShare {
|
||||
align-self: initial;
|
||||
margin-bottom: 5px;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
height: auto;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
|
||||
#filmstripLocalScreenShareThumbnail {
|
||||
width: calc(100% - 15px);
|
||||
#filmstripLocalScreenShareThumbnail {
|
||||
width: calc(100% - 15px);
|
||||
|
||||
.videocontainer {
|
||||
height: 0px;
|
||||
width: 100%;
|
||||
.videocontainer {
|
||||
height: 0px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove unnecssary padding that is normally used to prevent horizontal
|
||||
* filmstrip from overlapping the left edge of the screen.
|
||||
*/
|
||||
#filmstripLocalVideo,
|
||||
#filmstripLocalScreenShare,
|
||||
.remote-videos {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#remoteVideos {
|
||||
@include minHWAutoFix();
|
||||
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.resizable-filmstrip #remoteVideos .videocontainer {
|
||||
border-left: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&.reduce-height {
|
||||
height: calc(100% - calc(#{$newToolbarSizeWithPadding} + #{$scrollHeight}));
|
||||
}
|
||||
|
||||
.filmstrip__videos.vertical-view-grid#remoteVideos {
|
||||
align-items: 'center';
|
||||
border: 0px;
|
||||
padding-right: 7px;
|
||||
|
||||
&.has-scroll {
|
||||
padding-right: 0px;
|
||||
/**
|
||||
* Remove unnecssary padding that is normally used to prevent horizontal
|
||||
* filmstrip from overlapping the left edge of the screen.
|
||||
*/
|
||||
#filmstripLocalVideo,
|
||||
#filmstripLocalScreenShare,
|
||||
.remote-videos {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.remote-videos > div {
|
||||
left: 0px; // fixes an issue on FF - the div is aligned to the right by default for some reason
|
||||
#remoteVideos {
|
||||
@include minHWAutoFix();
|
||||
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.videocontainer {
|
||||
.resizable-filmstrip #remoteVideos .videocontainer {
|
||||
border-left: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&.reduce-height {
|
||||
height: calc(100% - calc(#{$newToolbarSizeWithPadding} + #{$scrollHeight}));
|
||||
}
|
||||
|
||||
.filmstrip__videos.vertical-view-grid#remoteVideos {
|
||||
align-items: 'center';
|
||||
border: 0px;
|
||||
margin: 2px;
|
||||
}
|
||||
}
|
||||
padding-right: 7px;
|
||||
|
||||
.remote-videos {
|
||||
display: flex;
|
||||
overscroll-behavior: contain;
|
||||
&.has-scroll {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
&.height-transition {
|
||||
transition: height .3s ease-in;
|
||||
.remote-videos > div {
|
||||
left: 0px; // fixes an issue on FF - the div is aligned to the right by default for some reason
|
||||
}
|
||||
|
||||
.videocontainer {
|
||||
border: 0px;
|
||||
margin: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
& > div {
|
||||
position: absolute;
|
||||
transition: opacity 1s;
|
||||
}
|
||||
.remote-videos {
|
||||
display: flex;
|
||||
overscroll-behavior: contain;
|
||||
|
||||
&.is-not-overflowing > div {
|
||||
bottom: 0px;
|
||||
&.height-transition {
|
||||
transition: height .3s ease-in;
|
||||
}
|
||||
|
||||
& > div {
|
||||
position: absolute;
|
||||
transition: opacity 1s;
|
||||
}
|
||||
|
||||
&.is-not-overflowing > div {
|
||||
bottom: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,14 +3,17 @@
|
|||
* clashing with the filmstrip.
|
||||
*/
|
||||
.vertical-filmstrip #etherpad,
|
||||
.vertical-filmstrip #sharedvideo {
|
||||
.stage-filmstrip #etherpad,
|
||||
.vertical-filmstrip #sharedvideo,
|
||||
.stage-filmstrip #sharedvideo {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides for small videos in vertical filmstrip mode.
|
||||
*/
|
||||
.vertical-filmstrip .filmstrip__videos .videocontainer {
|
||||
.vertical-filmstrip .filmstrip__videos .videocontainer,
|
||||
.stage-filmstrip .filmstrip__videos .videocontainer {
|
||||
.self-view-mobile-portrait video {
|
||||
object-fit: contain;
|
||||
}
|
||||
|
@ -27,7 +30,8 @@
|
|||
* The class opening is for when the filmstrip is transitioning from hidden
|
||||
* to visible.
|
||||
*/
|
||||
.vertical-filmstrip .large-video-labels {
|
||||
.vertical-filmstrip .large-video-labels,
|
||||
.stage-filmstrip .large-video-labels {
|
||||
&.with-filmstrip {
|
||||
right: 150px;
|
||||
}
|
||||
|
@ -47,6 +51,7 @@
|
|||
* Overrides for self view when in portrait mode on mobile.
|
||||
* This is done in order to keep the aspect ratio.
|
||||
*/
|
||||
.vertical-filmstrip .self-view-mobile-portrait #localVideo_container {
|
||||
.vertical-filmstrip .self-view-mobile-portrait #localVideo_container,
|
||||
.stage-filmstrip .self-view-mobile-portrait #localVideo_container {
|
||||
object-fit: contain;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import ReactDOM from 'react-dom';
|
|||
|
||||
import { browser } from '../../../react/features/base/lib-jitsi-meet';
|
||||
import { isTestModeEnabled } from '../../../react/features/base/testing';
|
||||
import { FILMSTRIP_BREAKPOINT, shouldDisplayStageFilmstrip } from '../../../react/features/filmstrip';
|
||||
import { FILMSTRIP_BREAKPOINT } from '../../../react/features/filmstrip';
|
||||
import { ORIENTATION, LargeVideoBackground, updateLastLargeVideoMediaEvent } from '../../../react/features/large-video';
|
||||
import { LAYOUTS, getCurrentLayout } from '../../../react/features/video-layout';
|
||||
/* eslint-enable no-unused-vars */
|
||||
|
@ -414,7 +414,7 @@ export class VideoContainer extends LargeContainer {
|
|||
|
||||
const verticalFilmstripWidth = state['features/filmstrip'].width?.current;
|
||||
|
||||
if (currentLayout === LAYOUTS.TILE_VIEW || shouldDisplayStageFilmstrip(state)) {
|
||||
if (currentLayout === LAYOUTS.TILE_VIEW || currentLayout === LAYOUTS.STAGE_FILMSTRIP_VIEW) {
|
||||
// We don't need to resize the large video since it won't be displayed and we'll resize when returning back
|
||||
// to stage view.
|
||||
return;
|
||||
|
|
|
@ -4,7 +4,7 @@ import { getGravatarURL } from '@jitsi/js-utils/avatar';
|
|||
import type { Store } from 'redux';
|
||||
|
||||
import { i18next } from '../../base/i18n';
|
||||
import { isStageFilmstripEnabled } from '../../filmstrip/functions';
|
||||
import { isStageFilmstripAvailable } from '../../filmstrip/functions';
|
||||
import { GRAVATAR_BASE_URL, isCORSAvatarURL } from '../avatar';
|
||||
import { getSourceNameSignalingFeatureFlag } from '../config';
|
||||
import { JitsiParticipantConnectionStatus } from '../lib-jitsi-meet';
|
||||
|
@ -372,7 +372,7 @@ export function getRemoteParticipantsSorted(stateful: Object | Function) {
|
|||
export function getPinnedParticipant(stateful: Object | Function) {
|
||||
const state = toState(stateful);
|
||||
const { pinnedParticipant } = state['features/base/participants'];
|
||||
const stageFilmstrip = isStageFilmstripEnabled(state);
|
||||
const stageFilmstrip = isStageFilmstripAvailable(state);
|
||||
|
||||
if (stageFilmstrip) {
|
||||
const { activeParticipants } = state['features/filmstrip'];
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import clsx from 'clsx';
|
||||
import _ from 'lodash';
|
||||
import React from 'react';
|
||||
|
||||
|
@ -12,7 +11,7 @@ import { translate } from '../../../base/i18n';
|
|||
import { connect as reactReduxConnect } from '../../../base/redux';
|
||||
import { setColorAlpha } from '../../../base/util';
|
||||
import { Chat } from '../../../chat';
|
||||
import { MainFilmstrip, StageFilmstrip, shouldDisplayStageFilmstrip } from '../../../filmstrip';
|
||||
import { MainFilmstrip, StageFilmstrip } from '../../../filmstrip';
|
||||
import { CalleeInfoContainer } from '../../../invite';
|
||||
import { LargeVideo } from '../../../large-video';
|
||||
import { LobbyScreen } from '../../../lobby';
|
||||
|
@ -59,7 +58,8 @@ const FULL_SCREEN_EVENTS = [
|
|||
export const LAYOUT_CLASSNAMES = {
|
||||
[LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW]: 'horizontal-filmstrip',
|
||||
[LAYOUTS.TILE_VIEW]: 'tile-view',
|
||||
[LAYOUTS.VERTICAL_FILMSTRIP_VIEW]: 'vertical-filmstrip'
|
||||
[LAYOUTS.VERTICAL_FILMSTRIP_VIEW]: 'vertical-filmstrip',
|
||||
[LAYOUTS.STAGE_FILMSTRIP_VIEW]: 'stage-filmstrip'
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -103,11 +103,6 @@ type Props = AbstractProps & {
|
|||
*/
|
||||
_showPrejoin: boolean,
|
||||
|
||||
/**
|
||||
* Whether or not the stage filmstrip should be displayed.
|
||||
*/
|
||||
_showStageFilmstrip: boolean,
|
||||
|
||||
dispatch: Function,
|
||||
t: Function
|
||||
}
|
||||
|
@ -220,8 +215,7 @@ class Conference extends AbstractConference<Props, *> {
|
|||
_notificationsVisible,
|
||||
_overflowDrawer,
|
||||
_showLobby,
|
||||
_showPrejoin,
|
||||
_showStageFilmstrip
|
||||
_showPrejoin
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
|
@ -233,7 +227,7 @@ class Conference extends AbstractConference<Props, *> {
|
|||
ref = { this._setBackground }>
|
||||
<Chat />
|
||||
<div
|
||||
className = { clsx(_layoutClassName, _showStageFilmstrip && 'stage-filmstrip') }
|
||||
className = { _layoutClassName }
|
||||
id = 'videoconference_page'
|
||||
onMouseMove = { isMobileBrowser() ? undefined : this._onShowToolbar }>
|
||||
<ConferenceInfo />
|
||||
|
@ -242,7 +236,7 @@ class Conference extends AbstractConference<Props, *> {
|
|||
id = 'videospace'
|
||||
onTouchStart = { this._onVidespaceTouchStart }>
|
||||
<LargeVideo />
|
||||
{_showStageFilmstrip && <StageFilmstrip />}
|
||||
<StageFilmstrip />
|
||||
<MainFilmstrip />
|
||||
</div>
|
||||
|
||||
|
@ -402,8 +396,7 @@ function _mapStateToProps(state) {
|
|||
_overflowDrawer: overflowDrawer,
|
||||
_roomName: getConferenceNameForTitle(state),
|
||||
_showLobby: getIsLobbyVisible(state),
|
||||
_showPrejoin: isPrejoinPageVisible(state),
|
||||
_showStageFilmstrip: shouldDisplayStageFilmstrip(state)
|
||||
_showPrejoin: isPrejoinPageVisible(state)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -36,11 +36,6 @@ type Props = {
|
|||
*/
|
||||
allowEditing: boolean,
|
||||
|
||||
/**
|
||||
* The current layout of the filmstrip.
|
||||
*/
|
||||
currentLayout: string,
|
||||
|
||||
/**
|
||||
* Invoked to update the participant's display name.
|
||||
*/
|
||||
|
@ -70,7 +65,12 @@ type Props = {
|
|||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
t: Function,
|
||||
|
||||
/**
|
||||
* The type of thumbnail.
|
||||
*/
|
||||
thumbnailType: string
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -183,11 +183,11 @@ class DisplayName extends Component<Props, State> {
|
|||
const {
|
||||
_nameToDisplay,
|
||||
allowEditing,
|
||||
currentLayout,
|
||||
displayNameSuffix,
|
||||
classes,
|
||||
elementID,
|
||||
t
|
||||
t,
|
||||
thumbnailType
|
||||
} = this.props;
|
||||
|
||||
if (allowEditing && this.state.isEditing) {
|
||||
|
@ -211,7 +211,7 @@ class DisplayName extends Component<Props, State> {
|
|||
return (
|
||||
<Tooltip
|
||||
content = { appendSuffix(_nameToDisplay, displayNameSuffix) }
|
||||
position = { getIndicatorsTooltipPosition(currentLayout) }>
|
||||
position = { getIndicatorsTooltipPosition(thumbnailType) }>
|
||||
<span
|
||||
className = { `displayname ${classes.displayName}` }
|
||||
id = { elementID }
|
||||
|
|
|
@ -171,7 +171,6 @@ export const SET_STAGE_PARTICIPANTS = 'SET_STAGE_PARTICIPANTS';
|
|||
*/
|
||||
export const SET_MAX_STAGE_PARTICIPANTS = 'SET_MAX_STAGE_PARTICIPANTS';
|
||||
|
||||
|
||||
/**
|
||||
* The type of Redux action which toggles the pin state of stage participants.
|
||||
* {
|
||||
|
@ -180,3 +179,11 @@ export const SET_MAX_STAGE_PARTICIPANTS = 'SET_MAX_STAGE_PARTICIPANTS';
|
|||
* }
|
||||
*/
|
||||
export const TOGGLE_PIN_STAGE_PARTICIPANT = 'TOGGLE_PIN_STAGE_PARTICIPANT';
|
||||
|
||||
/**
|
||||
* The type of Redux action which clears the list of stage participants.
|
||||
* {
|
||||
* type: CLEAR_STAGE_PARTICIPANTS
|
||||
* }
|
||||
*/
|
||||
export const CLEAR_STAGE_PARTICIPANTS = 'CLEAR_STAGE_PARTICIPANTS';
|
||||
|
|
|
@ -24,7 +24,8 @@ import {
|
|||
SET_VERTICAL_VIEW_DIMENSIONS,
|
||||
SET_VOLUME,
|
||||
SET_MAX_STAGE_PARTICIPANTS,
|
||||
TOGGLE_PIN_STAGE_PARTICIPANT
|
||||
TOGGLE_PIN_STAGE_PARTICIPANT,
|
||||
CLEAR_STAGE_PARTICIPANTS
|
||||
} from './actionTypes';
|
||||
import {
|
||||
HORIZONTAL_FILMSTRIP_MARGIN,
|
||||
|
@ -266,8 +267,6 @@ export function setStageFilmstripViewDimensions() {
|
|||
const state = getState();
|
||||
const { clientHeight, clientWidth } = state['features/base/responsive-ui'];
|
||||
const {
|
||||
disableResponsiveTiles,
|
||||
disableTileEnlargement,
|
||||
tileView = {}
|
||||
} = state['features/base/config'];
|
||||
const { visible } = state['features/filmstrip'];
|
||||
|
@ -282,17 +281,15 @@ export function setStageFilmstripViewDimensions() {
|
|||
width,
|
||||
columns,
|
||||
rows
|
||||
} = disableResponsiveTiles
|
||||
? calculateNonResponsiveTileViewDimensions(state, true)
|
||||
: calculateResponsiveTileViewDimensions({
|
||||
clientWidth: availableWidth,
|
||||
clientHeight,
|
||||
disableTileEnlargement,
|
||||
maxColumns,
|
||||
noHorizontalContainerMargin: verticalWidth > 0,
|
||||
numberOfParticipants,
|
||||
numberOfVisibleTiles
|
||||
});
|
||||
} = calculateResponsiveTileViewDimensions({
|
||||
clientWidth: availableWidth,
|
||||
clientHeight,
|
||||
disableTileEnlargement: false,
|
||||
maxColumns,
|
||||
noHorizontalContainerMargin: verticalWidth > 0,
|
||||
numberOfParticipants,
|
||||
numberOfVisibleTiles
|
||||
});
|
||||
const thumbnailsTotalHeight = rows * (TILE_VERTICAL_MARGIN + height);
|
||||
const hasScroll = clientHeight < thumbnailsTotalHeight;
|
||||
const filmstripWidth
|
||||
|
@ -469,3 +466,14 @@ export function togglePinStageParticipant(participantId) {
|
|||
participantId
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the stage participants list.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function clearStageParticipants() {
|
||||
return {
|
||||
type: CLEAR_STAGE_PARTICIPANTS
|
||||
};
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import { connect } from '../../../base/redux';
|
|||
import { shouldHideSelfView } from '../../../base/settings/functions.any';
|
||||
import { showToolbox } from '../../../toolbox/actions.web';
|
||||
import { isButtonEnabled, isToolboxVisible } from '../../../toolbox/functions.web';
|
||||
import { LAYOUTS } from '../../../video-layout';
|
||||
import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
|
||||
import {
|
||||
setFilmstripVisible,
|
||||
setVisibleRemoteParticipants,
|
||||
|
@ -110,7 +110,7 @@ type Props = {
|
|||
/**
|
||||
* The local screen share participant. This prop is behind the sourceNameSignaling feature flag.
|
||||
*/
|
||||
_localScreenShare: Object,
|
||||
_localScreenShare: Object,
|
||||
|
||||
/**
|
||||
* The maximum width of the vertical filmstrip.
|
||||
|
@ -318,32 +318,29 @@ class Filmstrip extends PureComponent <Props, State> {
|
|||
const { isMouseDown } = this.state;
|
||||
const tileViewActive = _currentLayout === LAYOUTS.TILE_VIEW;
|
||||
|
||||
switch (_currentLayout) {
|
||||
case LAYOUTS.VERTICAL_FILMSTRIP_VIEW: {
|
||||
if (_currentLayout === LAYOUTS.STAGE_FILMSTRIP_VIEW && _stageFilmstrip) {
|
||||
if (_visible) {
|
||||
filmstripStyle.maxWidth = `calc(100% - ${_verticalViewMaxWidth}px)`;
|
||||
}
|
||||
} else if (_currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW
|
||||
|| (_currentLayout === LAYOUTS.STAGE_FILMSTRIP_VIEW && !_stageFilmstrip)) {
|
||||
filmstripStyle.maxWidth = _verticalViewMaxWidth;
|
||||
if (!_visible) {
|
||||
filmstripStyle.right = `-${filmstripStyle.maxWidth}px`;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LAYOUTS.TILE_VIEW: {
|
||||
if (_stageFilmstrip && _visible) {
|
||||
filmstripStyle.maxWidth = `calc(100% - ${_verticalViewMaxWidth}px)`;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let toolbar = null;
|
||||
|
||||
if (!this.props._iAmRecorder && this.props._isFilmstripButtonEnabled && _currentLayout !== LAYOUTS.TILE_VIEW) {
|
||||
if (!this.props._iAmRecorder && this.props._isFilmstripButtonEnabled
|
||||
&& _currentLayout !== LAYOUTS.TILE_VIEW && !_stageFilmstrip) {
|
||||
toolbar = this._renderToggleButton();
|
||||
}
|
||||
|
||||
const filmstrip = (<>
|
||||
<div
|
||||
className = { clsx(this.props._videosClassName,
|
||||
!tileViewActive && !_resizableFilmstrip && 'filmstrip-hover',
|
||||
!tileViewActive && !_stageFilmstrip && !_resizableFilmstrip && 'filmstrip-hover',
|
||||
_verticalViewGrid && 'vertical-view-grid') }
|
||||
id = 'remoteVideos'>
|
||||
{!_disableSelfView && !_verticalViewGrid && (
|
||||
|
@ -351,7 +348,7 @@ class Filmstrip extends PureComponent <Props, State> {
|
|||
className = 'filmstrip__videos'
|
||||
id = 'filmstripLocalVideo'>
|
||||
{
|
||||
!tileViewActive && <div id = 'filmstripLocalVideoThumbnail'>
|
||||
!tileViewActive && !_stageFilmstrip && <div id = 'filmstripLocalVideoThumbnail'>
|
||||
<Thumbnail
|
||||
key = 'local' />
|
||||
</div>
|
||||
|
@ -364,7 +361,7 @@ class Filmstrip extends PureComponent <Props, State> {
|
|||
id = 'filmstripLocalScreenShare'>
|
||||
<div id = 'filmstripLocalScreenShareThumbnail'>
|
||||
{
|
||||
!tileViewActive && <Thumbnail
|
||||
!tileViewActive && !_stageFilmstrip && <Thumbnail
|
||||
key = 'localScreenShare'
|
||||
participantID = { _localScreenShare.id } />
|
||||
|
||||
|
@ -604,6 +601,7 @@ class Filmstrip extends PureComponent <Props, State> {
|
|||
_filmstripHeight,
|
||||
_filmstripWidth,
|
||||
_hasScroll,
|
||||
_isVerticalFilmstrip,
|
||||
_remoteParticipantsLength,
|
||||
_resizableFilmstrip,
|
||||
_rows,
|
||||
|
@ -619,7 +617,7 @@ class Filmstrip extends PureComponent <Props, State> {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (_currentLayout === LAYOUTS.TILE_VIEW || _verticalViewGrid) {
|
||||
if (_currentLayout === LAYOUTS.TILE_VIEW || _verticalViewGrid || _stageFilmstrip) {
|
||||
return (
|
||||
<FixedSizeGrid
|
||||
className = 'filmstrip__videos remote-videos'
|
||||
|
@ -669,7 +667,7 @@ class Filmstrip extends PureComponent <Props, State> {
|
|||
props.className += ' is-not-overflowing';
|
||||
}
|
||||
|
||||
} else if (_currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW) {
|
||||
} else if (_isVerticalFilmstrip) {
|
||||
const itemSize = _thumbnailHeight + TILE_VERTICAL_MARGIN;
|
||||
const isNotOverflowing = !_hasScroll;
|
||||
|
||||
|
@ -820,15 +818,20 @@ function _mapStateToProps(state, ownProps) {
|
|||
shouldReduceHeight ? 'reduce-height' : ''
|
||||
} ${shiftRight ? 'shift-right' : ''} ${collapseTileView ? 'collapse' : ''} ${visible ? '' : 'hidden'}`.trim();
|
||||
|
||||
const _currentLayout = getCurrentLayout(state);
|
||||
const _isVerticalFilmstrip = _currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW
|
||||
|| (!ownProps._stageFilmstrip && _currentLayout === LAYOUTS.STAGE_FILMSTRIP_VIEW);
|
||||
|
||||
return {
|
||||
_className: className,
|
||||
_chatOpen: state['features/chat'].isOpen,
|
||||
_currentLayout,
|
||||
_disableSelfView: disableSelfView,
|
||||
_hasScroll,
|
||||
_iAmRecorder: Boolean(iAmRecorder),
|
||||
_isFilmstripButtonEnabled: isButtonEnabled('filmstrip', state),
|
||||
_isToolboxVisible: isToolboxVisible(state),
|
||||
_isVerticalFilmstrip: ownProps._currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW,
|
||||
_isVerticalFilmstrip,
|
||||
_localScreenShare: getSourceNameSignalingFeatureFlag(state) && localScreenShare,
|
||||
_maxFilmstripWidth: clientWidth - MIN_STAGE_VIEW_WIDTH,
|
||||
_thumbnailsReordered: enableThumbnailReordering,
|
||||
|
|
|
@ -17,11 +17,6 @@ import Filmstrip from './Filmstrip';
|
|||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The current layout of the filmstrip.
|
||||
*/
|
||||
_currentLayout: string,
|
||||
|
||||
/**
|
||||
* The number of columns in tile view.
|
||||
*/
|
||||
|
@ -143,7 +138,8 @@ function _mapStateToProps(state) {
|
|||
&& clientWidth <= ASPECT_RATIO_BREAKPOINT;
|
||||
|
||||
const shouldReduceHeight = reduceHeight && (
|
||||
isMobileBrowser() || _currentLayout !== LAYOUTS.VERTICAL_FILMSTRIP_VIEW);
|
||||
isMobileBrowser() || (_currentLayout !== LAYOUTS.VERTICAL_FILMSTRIP_VIEW
|
||||
&& _currentLayout !== LAYOUTS.STAGE_FILMSTRIP_VIEW));
|
||||
|
||||
let _thumbnailSize, remoteFilmstripHeight, remoteFilmstripWidth;
|
||||
|
||||
|
@ -154,7 +150,8 @@ function _mapStateToProps(state) {
|
|||
remoteFilmstripHeight = filmstripHeight - (collapseTileView && filmstripPadding > 0 ? filmstripPadding : 0);
|
||||
remoteFilmstripWidth = filmstripWidth;
|
||||
break;
|
||||
case LAYOUTS.VERTICAL_FILMSTRIP_VIEW: {
|
||||
case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
|
||||
case LAYOUTS.STAGE_FILMSTRIP_VIEW: {
|
||||
const {
|
||||
remote,
|
||||
remoteVideosContainer,
|
||||
|
@ -189,7 +186,6 @@ function _mapStateToProps(state) {
|
|||
|
||||
return {
|
||||
_columns: gridDimensions.columns,
|
||||
_currentLayout,
|
||||
_filmstripHeight: remoteFilmstripHeight,
|
||||
_filmstripWidth: remoteFilmstripWidth,
|
||||
_hasScroll,
|
||||
|
|
|
@ -92,11 +92,10 @@ type Props = {
|
|||
_visible: boolean
|
||||
};
|
||||
|
||||
const StageFilmstrip = (props: Props) => props._currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW && (
|
||||
const StageFilmstrip = (props: Props) => props._currentLayout === LAYOUTS.STAGE_FILMSTRIP_VIEW && (
|
||||
<span className = { LAYOUT_CLASSNAMES[LAYOUTS.TILE_VIEW] }>
|
||||
<Filmstrip
|
||||
{ ...props }
|
||||
_currentLayout = { LAYOUTS.TILE_VIEW }
|
||||
_stageFilmstrip = { true } />
|
||||
</span>
|
||||
);
|
||||
|
|
|
@ -6,7 +6,6 @@ import { MEDIA_TYPE } from '../../../base/media';
|
|||
import { getParticipantByIdOrUndefined, PARTICIPANT_ROLE } from '../../../base/participants';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { getTrackByMediaTypeAndParticipant, isLocalTrackMuted, isRemoteTrackMuted } from '../../../base/tracks';
|
||||
import { getCurrentLayout } from '../../../video-layout';
|
||||
import { getIndicatorsTooltipPosition } from '../../functions.web';
|
||||
|
||||
import AudioMutedIndicator from './AudioMutedIndicator';
|
||||
|
@ -20,11 +19,6 @@ declare var interfaceConfig: Object;
|
|||
*/
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The current layout of the filmstrip.
|
||||
*/
|
||||
_currentLayout: string,
|
||||
|
||||
/**
|
||||
* Indicates if the audio muted indicator should be visible or not.
|
||||
*/
|
||||
|
@ -43,7 +37,12 @@ type Props = {
|
|||
/**
|
||||
* The ID of the participant for which the status bar is rendered.
|
||||
*/
|
||||
participantID: String
|
||||
participantID: String,
|
||||
|
||||
/**
|
||||
* The type of thumbnail.
|
||||
*/
|
||||
thumbnailType: string
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -60,12 +59,12 @@ class StatusIndicators extends Component<Props> {
|
|||
*/
|
||||
render() {
|
||||
const {
|
||||
_currentLayout,
|
||||
_showAudioMutedIndicator,
|
||||
_showModeratorIndicator,
|
||||
_showScreenShareIndicator
|
||||
_showScreenShareIndicator,
|
||||
thumbnailType
|
||||
} = this.props;
|
||||
const tooltipPosition = getIndicatorsTooltipPosition(_currentLayout);
|
||||
const tooltipPosition = getIndicatorsTooltipPosition(thumbnailType);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -111,7 +110,6 @@ function _mapStateToProps(state, ownProps) {
|
|||
const { disableModeratorIndicator } = state['features/base/config'];
|
||||
|
||||
return {
|
||||
_currentLayout: getCurrentLayout(state),
|
||||
_showAudioMutedIndicator: isAudioMuted && audio,
|
||||
_showModeratorIndicator:
|
||||
!disableModeratorIndicator && participant && participant.role === PARTICIPANT_ROLE.MODERATOR && moderator,
|
||||
|
|
|
@ -36,6 +36,7 @@ import {
|
|||
DISPLAY_MODE_TO_CLASS_NAME,
|
||||
DISPLAY_VIDEO,
|
||||
SHOW_TOOLBAR_CONTEXT_MENU_AFTER,
|
||||
THUMBNAIL_TYPE,
|
||||
VIDEO_TEST_EVENTS
|
||||
} from '../../constants';
|
||||
import {
|
||||
|
@ -44,9 +45,9 @@ import {
|
|||
getDisplayModeInput,
|
||||
isVideoPlayable,
|
||||
showGridInVerticalView,
|
||||
isStageFilmstripEnabled,
|
||||
shouldDisplayStageFilmstrip
|
||||
isStageFilmstripAvailable
|
||||
} from '../../functions';
|
||||
import { getThumbnailTypeFromLayout } from '../../functions.web';
|
||||
|
||||
import FakeScreenShareParticipant from './FakeScreenShareParticipant';
|
||||
import ThumbnailAudioIndicator from './ThumbnailAudioIndicator';
|
||||
|
@ -91,11 +92,6 @@ export type Props = {|
|
|||
*/
|
||||
_audioTrack: ?Object,
|
||||
|
||||
/**
|
||||
* The current layout of the filmstrip.
|
||||
*/
|
||||
_currentLayout: string,
|
||||
|
||||
/**
|
||||
* Indicates whether the local video flip feature is disabled or not.
|
||||
*/
|
||||
|
@ -189,9 +185,9 @@ export type Props = {|
|
|||
_raisedHand: boolean,
|
||||
|
||||
/**
|
||||
* Whether or not the stage filmstrip is disabled.
|
||||
* Whether or not the current layout is stage filmstrip layout.
|
||||
*/
|
||||
_stageFilmstripDisabled: boolean,
|
||||
_stageFilmstripLayout: boolean,
|
||||
|
||||
/**
|
||||
* Whether or not the participants are displayed on stage.
|
||||
|
@ -200,6 +196,11 @@ export type Props = {|
|
|||
*/
|
||||
_stageParticipantsVisible: boolean,
|
||||
|
||||
/**
|
||||
* The type of thumbnail to display.
|
||||
*/
|
||||
_thumbnailType: string,
|
||||
|
||||
/**
|
||||
* The video object position for the participant.
|
||||
*/
|
||||
|
@ -447,15 +448,15 @@ class Thumbnail extends Component<Props, State> {
|
|||
*/
|
||||
_maybeSendScreenSharingIssueEvents(input) {
|
||||
const {
|
||||
_currentLayout,
|
||||
_isAudioOnly,
|
||||
_isScreenSharing
|
||||
_isScreenSharing,
|
||||
_thumbnailType
|
||||
} = this.props;
|
||||
const { displayMode } = this.state;
|
||||
const tileViewActive = _currentLayout === LAYOUTS.TILE_VIEW;
|
||||
const isTileType = _thumbnailType === THUMBNAIL_TYPE.TILE;
|
||||
|
||||
if (!(DISPLAY_VIDEO === displayMode)
|
||||
&& tileViewActive
|
||||
&& isTileType
|
||||
&& _isScreenSharing
|
||||
&& !_isAudioOnly) {
|
||||
sendAnalytics(createScreenSharingIssueEvent({
|
||||
|
@ -530,9 +531,9 @@ class Thumbnail extends Component<Props, State> {
|
|||
* @returns {void}
|
||||
*/
|
||||
_hidePopover() {
|
||||
const { _currentLayout } = this.props;
|
||||
const { _thumbnailType } = this.props;
|
||||
|
||||
if (_currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW) {
|
||||
if (_thumbnailType === THUMBNAIL_TYPE.VERTICAL) {
|
||||
this.setState({
|
||||
isHovered: false
|
||||
});
|
||||
|
@ -550,13 +551,13 @@ class Thumbnail extends Component<Props, State> {
|
|||
_getStyles(): Object {
|
||||
const { canPlayEventReceived } = this.state;
|
||||
const {
|
||||
_currentLayout,
|
||||
_disableTileEnlargement,
|
||||
_height,
|
||||
_isFakeScreenShareParticipant,
|
||||
_isHidden,
|
||||
_isScreenSharing,
|
||||
_participant,
|
||||
_thumbnailType,
|
||||
_videoObjectPosition,
|
||||
_videoTrack,
|
||||
_width,
|
||||
|
@ -564,7 +565,7 @@ class Thumbnail extends Component<Props, State> {
|
|||
style
|
||||
} = this.props;
|
||||
|
||||
const tileViewActive = _currentLayout === LAYOUTS.TILE_VIEW;
|
||||
const isTileType = _thumbnailType === THUMBNAIL_TYPE.TILE;
|
||||
const jitsiVideoTrack = _videoTrack?.jitsiTrack;
|
||||
const track = jitsiVideoTrack?.track;
|
||||
const isPortraitVideo = ((track && track.getSettings()?.aspectRatio) || 1) < 1;
|
||||
|
@ -587,7 +588,7 @@ class Thumbnail extends Component<Props, State> {
|
|||
}
|
||||
|
||||
let videoStyles = null;
|
||||
const doNotStretchVideo = (isPortraitVideo && tileViewActive)
|
||||
const doNotStretchVideo = (isPortraitVideo && isTileType)
|
||||
|| _disableTileEnlargement
|
||||
|| _isScreenSharing;
|
||||
|
||||
|
@ -636,13 +637,13 @@ class Thumbnail extends Component<Props, State> {
|
|||
* @returns {void}
|
||||
*/
|
||||
_onClick() {
|
||||
const { _participant, dispatch, _stageFilmstripDisabled } = this.props;
|
||||
const { _participant, dispatch, _stageFilmstripLayout } = this.props;
|
||||
const { id, pinned } = _participant;
|
||||
|
||||
if (_stageFilmstripDisabled) {
|
||||
dispatch(pinParticipant(pinned ? null : id));
|
||||
} else {
|
||||
if (_stageFilmstripLayout) {
|
||||
dispatch(togglePinStageParticipant(id));
|
||||
} else {
|
||||
dispatch(pinParticipant(pinned ? null : id));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -790,8 +791,8 @@ class Thumbnail extends Component<Props, State> {
|
|||
const {
|
||||
_isDominantSpeakerDisabled,
|
||||
_participant,
|
||||
_currentLayout,
|
||||
_raisedHand,
|
||||
_thumbnailType,
|
||||
classes
|
||||
} = this.props;
|
||||
|
||||
|
@ -804,7 +805,7 @@ class Thumbnail extends Component<Props, State> {
|
|||
if (!_isDominantSpeakerDisabled && _participant?.dominantSpeaker) {
|
||||
className += ` ${classes.activeSpeaker} dominant-speaker`;
|
||||
}
|
||||
if (_currentLayout !== LAYOUTS.TILE_VIEW && _participant?.pinned) {
|
||||
if (_thumbnailType !== THUMBNAIL_TYPE.TILE && _participant?.pinned) {
|
||||
className += ' videoContainerFocused';
|
||||
}
|
||||
|
||||
|
@ -902,16 +903,16 @@ class Thumbnail extends Component<Props, State> {
|
|||
_renderParticipant(local = false) {
|
||||
const {
|
||||
_audioTrack,
|
||||
_currentLayout,
|
||||
_disableLocalVideoFlip,
|
||||
_gifSrc,
|
||||
_isMobile,
|
||||
_isMobilePortrait,
|
||||
_isScreenSharing,
|
||||
_isTestModeEnabled,
|
||||
_localFlipX,
|
||||
_participant,
|
||||
_thumbnailType,
|
||||
_videoTrack,
|
||||
_gifSrc,
|
||||
classes,
|
||||
stageFilmstrip
|
||||
} = this.props;
|
||||
|
@ -975,28 +976,28 @@ class Thumbnail extends Component<Props, State> {
|
|||
<div
|
||||
className = { clsx(classes.indicatorsContainer,
|
||||
classes.indicatorsTopContainer,
|
||||
_currentLayout === LAYOUTS.TILE_VIEW && 'tile-view-mode'
|
||||
_thumbnailType === THUMBNAIL_TYPE.TILE && 'tile-view-mode'
|
||||
) }>
|
||||
<ThumbnailTopIndicators
|
||||
currentLayout = { _currentLayout }
|
||||
hidePopover = { this._hidePopover }
|
||||
indicatorsClassName = { classes.indicatorsBackground }
|
||||
isHovered = { isHovered }
|
||||
local = { local }
|
||||
participantId = { id }
|
||||
popoverVisible = { popoverVisible }
|
||||
showPopover = { this._showPopover } />
|
||||
showPopover = { this._showPopover }
|
||||
thumbnailType = { _thumbnailType } />
|
||||
</div>
|
||||
<div
|
||||
className = { clsx(classes.indicatorsContainer,
|
||||
classes.indicatorsBottomContainer,
|
||||
_currentLayout === LAYOUTS.TILE_VIEW && 'tile-view-mode'
|
||||
_thumbnailType === THUMBNAIL_TYPE.TILE && 'tile-view-mode'
|
||||
) }>
|
||||
<ThumbnailBottomIndicators
|
||||
className = { classes.indicatorsBackground }
|
||||
currentLayout = { _currentLayout }
|
||||
local = { local }
|
||||
participantId = { id } />
|
||||
participantId = { id }
|
||||
thumbnailType = { _thumbnailType } />
|
||||
</div>
|
||||
{!_gifSrc && this._renderAvatar(styles.avatar) }
|
||||
{ !local && (
|
||||
|
@ -1103,7 +1104,7 @@ function _mapStateToProps(state, ownProps): Object {
|
|||
}
|
||||
const _audioTrack = isLocal
|
||||
? getLocalAudioTrack(tracks) : getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.AUDIO, participantID);
|
||||
const _currentLayout = stageFilmstrip ? LAYOUTS.TILE_VIEW : getCurrentLayout(state);
|
||||
const _currentLayout = getCurrentLayout(state);
|
||||
let size = {};
|
||||
let _isMobilePortrait = false;
|
||||
const {
|
||||
|
@ -1116,10 +1117,12 @@ function _mapStateToProps(state, ownProps): Object {
|
|||
const { localFlipX } = state['features/base/settings'];
|
||||
const _isMobile = isMobileBrowser();
|
||||
const activeParticipants = getActiveParticipantsIds(state);
|
||||
const tileType = getThumbnailTypeFromLayout(_currentLayout, stageFilmstrip);
|
||||
|
||||
switch (_currentLayout) {
|
||||
case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
|
||||
case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW: {
|
||||
|
||||
switch (tileType) {
|
||||
case THUMBNAIL_TYPE.VERTICAL:
|
||||
case THUMBNAIL_TYPE.HORIZONTAL: {
|
||||
const {
|
||||
horizontalViewDimensions = {
|
||||
local: {},
|
||||
|
@ -1133,7 +1136,7 @@ function _mapStateToProps(state, ownProps): Object {
|
|||
} = state['features/filmstrip'];
|
||||
const _verticalViewGrid = showGridInVerticalView(state);
|
||||
const { local, remote }
|
||||
= _currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW
|
||||
= tileType === THUMBNAIL_TYPE.VERTICAL
|
||||
? verticalViewDimensions : horizontalViewDimensions;
|
||||
const { width, height } = (isLocal ? local : remote) ?? {};
|
||||
|
||||
|
@ -1155,7 +1158,7 @@ function _mapStateToProps(state, ownProps): Object {
|
|||
|
||||
break;
|
||||
}
|
||||
case LAYOUTS.TILE_VIEW: {
|
||||
case THUMBNAIL_TYPE.TILE: {
|
||||
const { thumbnailSize } = state['features/filmstrip'].tileViewDimensions;
|
||||
const {
|
||||
stageFilmstripDimensions = {
|
||||
|
@ -1186,7 +1189,6 @@ function _mapStateToProps(state, ownProps): Object {
|
|||
|
||||
return {
|
||||
_audioTrack,
|
||||
_currentLayout,
|
||||
_defaultLocalDisplayName: defaultLocalDisplayName,
|
||||
_disableLocalVideoFlip: Boolean(disableLocalVideoFlip),
|
||||
_disableTileEnlargement: Boolean(disableTileEnlargement),
|
||||
|
@ -1204,8 +1206,9 @@ function _mapStateToProps(state, ownProps): Object {
|
|||
_localFlipX: Boolean(localFlipX),
|
||||
_participant: participant,
|
||||
_raisedHand: hasRaisedHand(participant),
|
||||
_stageFilmstripDisabled: !isStageFilmstripEnabled(state),
|
||||
_stageParticipantsVisible: shouldDisplayStageFilmstrip(state, 1),
|
||||
_stageFilmstripLayout: isStageFilmstripAvailable(state),
|
||||
_stageParticipantsVisible: _currentLayout === LAYOUTS.STAGE_FILMSTRIP_VIEW,
|
||||
_thumbnailType: tileType,
|
||||
_videoObjectPosition: getVideoObjectPosition(state, participant?.id),
|
||||
_videoTrack,
|
||||
...size,
|
||||
|
|
|
@ -6,7 +6,7 @@ import { useSelector } from 'react-redux';
|
|||
|
||||
import { isDisplayNameVisible, isNameReadOnly } from '../../../base/config/functions.any';
|
||||
import DisplayName from '../../../display-name/components/web/DisplayName';
|
||||
import { LAYOUTS } from '../../../video-layout';
|
||||
import { THUMBNAIL_TYPE } from '../../constants';
|
||||
|
||||
import StatusIndicators from './StatusIndicators';
|
||||
|
||||
|
@ -14,11 +14,6 @@ declare var interfaceConfig: Object;
|
|||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The current layout of the filmstrip.
|
||||
*/
|
||||
currentLayout: string,
|
||||
|
||||
/**
|
||||
* Class name for indicators container.
|
||||
*/
|
||||
|
@ -37,7 +32,12 @@ type Props = {
|
|||
/**
|
||||
* Whether or not to show the status indicators.
|
||||
*/
|
||||
showStatusIndicators: string
|
||||
showStatusIndicators: string,
|
||||
|
||||
/**
|
||||
* The type of thumbnail.
|
||||
*/
|
||||
thumbnailType: string
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(() => {
|
||||
|
@ -61,10 +61,10 @@ const useStyles = makeStyles(() => {
|
|||
|
||||
const ThumbnailBottomIndicators = ({
|
||||
className,
|
||||
currentLayout,
|
||||
local,
|
||||
participantId,
|
||||
showStatusIndicators = true
|
||||
showStatusIndicators = true,
|
||||
thumbnailType
|
||||
}: Props) => {
|
||||
const styles = useStyles();
|
||||
const _allowEditing = !useSelector(isNameReadOnly);
|
||||
|
@ -77,17 +77,18 @@ const ThumbnailBottomIndicators = ({
|
|||
audio = { true }
|
||||
moderator = { true }
|
||||
participantID = { participantId }
|
||||
screenshare = { currentLayout === LAYOUTS.TILE_VIEW } />
|
||||
screenshare = { thumbnailType === THUMBNAIL_TYPE.TILE }
|
||||
thumbnailType = { thumbnailType } />
|
||||
}
|
||||
{
|
||||
_showDisplayName && (
|
||||
<span className = { styles.nameContainer }>
|
||||
<DisplayName
|
||||
allowEditing = { local ? _allowEditing : false }
|
||||
currentLayout = { currentLayout }
|
||||
displayNameSuffix = { local ? _defaultLocalDisplayName : '' }
|
||||
elementID = { local ? 'localDisplayName' : `participant_${participantId}_name` }
|
||||
participantID = { participantId } />
|
||||
participantID = { participantId }
|
||||
thumbnailType = { thumbnailType } />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,8 +8,7 @@ import { useSelector } from 'react-redux';
|
|||
import { getSourceNameSignalingFeatureFlag } from '../../../base/config';
|
||||
import { isMobileBrowser } from '../../../base/environment/utils';
|
||||
import ConnectionIndicator from '../../../connection-indicator/components/web/ConnectionIndicator';
|
||||
import { LAYOUTS } from '../../../video-layout';
|
||||
import { STATS_POPOVER_POSITION } from '../../constants';
|
||||
import { STATS_POPOVER_POSITION, THUMBNAIL_TYPE } from '../../constants';
|
||||
import { getIndicatorsTooltipPosition } from '../../functions.web';
|
||||
|
||||
import PinnedIndicator from './PinnedIndicator';
|
||||
|
@ -21,11 +20,6 @@ declare var interfaceConfig: Object;
|
|||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The current layout of the filmstrip.
|
||||
*/
|
||||
currentLayout: string,
|
||||
|
||||
/**
|
||||
* Hide popover callback.
|
||||
*/
|
||||
|
@ -64,7 +58,12 @@ type Props = {
|
|||
/**
|
||||
* Show popover callback.
|
||||
*/
|
||||
showPopover: Function
|
||||
showPopover: Function,
|
||||
|
||||
/**
|
||||
* The type of thumbnail.
|
||||
*/
|
||||
thumbnailType: string
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(() => {
|
||||
|
@ -80,7 +79,6 @@ const useStyles = makeStyles(() => {
|
|||
});
|
||||
|
||||
const ThumbnailTopIndicators = ({
|
||||
currentLayout,
|
||||
hidePopover,
|
||||
indicatorsClassName,
|
||||
isFakeScreenShareParticipant,
|
||||
|
@ -88,7 +86,8 @@ const ThumbnailTopIndicators = ({
|
|||
local,
|
||||
participantId,
|
||||
popoverVisible,
|
||||
showPopover
|
||||
showPopover,
|
||||
thumbnailType
|
||||
}: Props) => {
|
||||
const styles = useStyles();
|
||||
|
||||
|
@ -111,32 +110,34 @@ const ThumbnailTopIndicators = ({
|
|||
enableStatsDisplay = { true }
|
||||
iconSize = { _indicatorIconSize }
|
||||
participantId = { participantId }
|
||||
statsPopoverPosition = { STATS_POPOVER_POSITION[currentLayout] } />
|
||||
statsPopoverPosition = { STATS_POPOVER_POSITION[thumbnailType] } />
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const tooltipPosition = getIndicatorsTooltipPosition(thumbnailType);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className = { styles.container }>
|
||||
<PinnedIndicator
|
||||
iconSize = { _indicatorIconSize }
|
||||
participantId = { participantId }
|
||||
tooltipPosition = { getIndicatorsTooltipPosition(currentLayout) } />
|
||||
tooltipPosition = { tooltipPosition } />
|
||||
{!_connectionIndicatorDisabled
|
||||
&& <ConnectionIndicator
|
||||
alwaysVisible = { showConnectionIndicator }
|
||||
enableStatsDisplay = { true }
|
||||
iconSize = { _indicatorIconSize }
|
||||
participantId = { participantId }
|
||||
statsPopoverPosition = { STATS_POPOVER_POSITION[currentLayout] } />
|
||||
statsPopoverPosition = { STATS_POPOVER_POSITION[thumbnailType] } />
|
||||
}
|
||||
<RaisedHandIndicator
|
||||
iconSize = { _indicatorIconSize }
|
||||
participantId = { participantId }
|
||||
tooltipPosition = { getIndicatorsTooltipPosition(currentLayout) } />
|
||||
{currentLayout !== LAYOUTS.TILE_VIEW && (
|
||||
tooltipPosition = { tooltipPosition } />
|
||||
{thumbnailType !== THUMBNAIL_TYPE.TILE && (
|
||||
<div className = { clsx(indicatorsClassName, 'top-indicators') }>
|
||||
<StatusIndicators
|
||||
participantID = { participantId }
|
||||
|
@ -146,12 +147,12 @@ const ThumbnailTopIndicators = ({
|
|||
</div>
|
||||
<div className = { styles.container }>
|
||||
<VideoMenuTriggerButton
|
||||
currentLayout = { currentLayout }
|
||||
hidePopover = { hidePopover }
|
||||
local = { local }
|
||||
participantId = { participantId }
|
||||
popoverVisible = { popoverVisible }
|
||||
showPopover = { showPopover }
|
||||
thumbnailType = { thumbnailType }
|
||||
visible = { isHovered } />
|
||||
</div>
|
||||
</>);
|
||||
|
|
|
@ -6,11 +6,6 @@ import { LocalVideoMenuTriggerButton, RemoteVideoMenuTriggerButton } from '../..
|
|||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The current layout of the filmstrip.
|
||||
*/
|
||||
currentLayout: string,
|
||||
|
||||
/**
|
||||
* Hide popover callback.
|
||||
*/
|
||||
|
@ -36,6 +31,11 @@ type Props = {
|
|||
*/
|
||||
showPopover: Function,
|
||||
|
||||
/**
|
||||
* The type of thumbnail.
|
||||
*/
|
||||
thumbnailType: string,
|
||||
|
||||
/**
|
||||
* Whether or not the component is visible.
|
||||
*/
|
||||
|
@ -44,33 +44,33 @@ type Props = {
|
|||
|
||||
// eslint-disable-next-line no-confusing-arrow
|
||||
const VideoMenuTriggerButton = ({
|
||||
currentLayout,
|
||||
hidePopover,
|
||||
local,
|
||||
participantId,
|
||||
popoverVisible,
|
||||
showPopover,
|
||||
thumbnailType,
|
||||
visible
|
||||
}: Props) => local
|
||||
? (
|
||||
<span id = 'localvideomenu'>
|
||||
<LocalVideoMenuTriggerButton
|
||||
buttonVisible = { visible }
|
||||
currentLayout = { currentLayout }
|
||||
hidePopover = { hidePopover }
|
||||
popoverVisible = { popoverVisible }
|
||||
showPopover = { showPopover } />
|
||||
showPopover = { showPopover }
|
||||
thumbnailType = { thumbnailType } />
|
||||
</span>
|
||||
)
|
||||
: (
|
||||
<span id = 'remotevideomenu'>
|
||||
<RemoteVideoMenuTriggerButton
|
||||
buttonVisible = { visible }
|
||||
currentLayout = { currentLayout }
|
||||
hidePopover = { hidePopover }
|
||||
participantID = { participantId }
|
||||
popoverVisible = { popoverVisible }
|
||||
showPopover = { showPopover } />
|
||||
showPopover = { showPopover }
|
||||
thumbnailType = { thumbnailType } />
|
||||
</span>
|
||||
);
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// @flow
|
||||
|
||||
import { BoxModel } from '../base/styles';
|
||||
import { LAYOUTS } from '../video-layout/constants';
|
||||
|
||||
/**
|
||||
* The size (height and width) of the small (not tile view) thumbnails.
|
||||
|
@ -228,22 +227,31 @@ export const SHOW_TOOLBAR_CONTEXT_MENU_AFTER = 600;
|
|||
*/
|
||||
export const TILE_MARGIN = 10;
|
||||
|
||||
/**
|
||||
* The types of thumbnails for filmstrip.
|
||||
*/
|
||||
export const THUMBNAIL_TYPE = {
|
||||
TILE: 'TILE',
|
||||
VERTICAL: 'VERTICAL',
|
||||
HORIZONTAL: 'HORIZONTAL'
|
||||
};
|
||||
|
||||
/**
|
||||
* The popover position for the connection stats table.
|
||||
*/
|
||||
export const STATS_POPOVER_POSITION = {
|
||||
[LAYOUTS.TILE_VIEW]: 'right-start',
|
||||
[LAYOUTS.VERTICAL_FILMSTRIP_VIEW]: 'left-start',
|
||||
[LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW]: 'top-end'
|
||||
[THUMBNAIL_TYPE.TILE]: 'right-start',
|
||||
[THUMBNAIL_TYPE.VERTICAL]: 'left-start',
|
||||
[THUMBNAIL_TYPE.HORIZONTAL]: 'top-end'
|
||||
};
|
||||
|
||||
/**
|
||||
* The tooltip position for the indicators on the thumbnail.
|
||||
*/
|
||||
export const INDICATORS_TOOLTIP_POSITION = {
|
||||
[LAYOUTS.TILE_VIEW]: 'right',
|
||||
[LAYOUTS.VERTICAL_FILMSTRIP_VIEW]: 'left',
|
||||
[LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW]: 'top'
|
||||
[THUMBNAIL_TYPE.TILE]: 'right',
|
||||
[THUMBNAIL_TYPE.VERTICAL]: 'left',
|
||||
[THUMBNAIL_TYPE.HORIZONTAL]: 'top'
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -103,11 +103,11 @@ export function isReorderingEnabled(state) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Whether the stage filmstrip is disabled or not.
|
||||
* Whether the stage filmstrip is available or not.
|
||||
*
|
||||
* @param {Object} state - Redux state.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isStageFilmstripEnabled() {
|
||||
export function isStageFilmstripAvailable() {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import {
|
|||
INDICATORS_TOOLTIP_POSITION,
|
||||
SCROLL_SIZE,
|
||||
SQUARE_TILE_ASPECT_RATIO,
|
||||
THUMBNAIL_TYPE,
|
||||
TILE_ASPECT_RATIO,
|
||||
TILE_HORIZONTAL_MARGIN,
|
||||
TILE_MIN_HEIGHT_LARGE,
|
||||
|
@ -243,18 +244,16 @@ export function getNumberOfPartipantsForTileView(state) {
|
|||
* disabled.
|
||||
*
|
||||
* @param {Object} state - The redux store state.
|
||||
* @param {boolean} stageFilmstrip - Whether the dimensions should be calculated for the stage filmstrip.
|
||||
* @returns {Object} - The dimensions.
|
||||
*/
|
||||
export function calculateNonResponsiveTileViewDimensions(state, stageFilmstrip = false) {
|
||||
export function calculateNonResponsiveTileViewDimensions(state) {
|
||||
const { clientHeight, clientWidth } = state['features/base/responsive-ui'];
|
||||
const { disableTileEnlargement } = state['features/base/config'];
|
||||
const { columns: c, minVisibleRows, rows: r } = getNotResponsiveTileViewGridDimensions(state, stageFilmstrip);
|
||||
const filmstripWidth = getVerticalViewMaxWidth(state);
|
||||
const { columns: c, minVisibleRows, rows: r } = getNotResponsiveTileViewGridDimensions(state);
|
||||
const size = calculateThumbnailSizeForTileView({
|
||||
columns: c,
|
||||
minVisibleRows,
|
||||
clientWidth: clientWidth - (stageFilmstrip ? filmstripWidth : 0),
|
||||
clientWidth,
|
||||
clientHeight,
|
||||
disableTileEnlargement,
|
||||
disableResponsiveTiles: true
|
||||
|
@ -515,6 +514,7 @@ export function computeDisplayModeFromInput(input: Object) {
|
|||
canPlayEventReceived,
|
||||
isRemoteParticipant,
|
||||
stageParticipantsVisible,
|
||||
stageFilmstrip,
|
||||
tileViewActive
|
||||
} = input;
|
||||
const adjustedIsVideoPlayable = input.isVideoPlayable && (!isRemoteParticipant || canPlayEventReceived);
|
||||
|
@ -524,7 +524,7 @@ export function computeDisplayModeFromInput(input: Object) {
|
|||
}
|
||||
|
||||
if (!tileViewActive && ((isScreenSharing && isRemoteParticipant)
|
||||
|| (stageParticipantsVisible && isActiveParticipant))) {
|
||||
|| (stageParticipantsVisible && isActiveParticipant && !stageFilmstrip))) {
|
||||
return DISPLAY_AVATAR;
|
||||
} else if (isCurrentlyOnLargeVideo && !tileViewActive) {
|
||||
// Display name is always and only displayed when user is on the stage
|
||||
|
@ -556,7 +556,8 @@ export function getDisplayModeInput(props: Object, state: Object) {
|
|||
_isVideoPlayable,
|
||||
_participant,
|
||||
_stageParticipantsVisible,
|
||||
_videoTrack
|
||||
_videoTrack,
|
||||
stageFilmstrip
|
||||
} = props;
|
||||
const tileViewActive = _currentLayout === LAYOUTS.TILE_VIEW;
|
||||
const { canPlayEventReceived } = state;
|
||||
|
@ -574,6 +575,7 @@ export function getDisplayModeInput(props: Object, state: Object) {
|
|||
isScreenSharing: _isScreenSharing,
|
||||
isFakeScreenShareParticipant: _isFakeScreenShareParticipant,
|
||||
stageParticipantsVisible: _stageParticipantsVisible,
|
||||
stageFilmstrip,
|
||||
videoStreamMuted: _videoTrack ? _videoTrack.muted : 'no stream'
|
||||
};
|
||||
}
|
||||
|
@ -581,11 +583,11 @@ export function getDisplayModeInput(props: Object, state: Object) {
|
|||
/**
|
||||
* Gets the tooltip position for the thumbnail indicators.
|
||||
*
|
||||
* @param {string} currentLayout - The current layout of the app.
|
||||
* @param {string} thumbnailType - The current thumbnail type.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getIndicatorsTooltipPosition(currentLayout: string) {
|
||||
return INDICATORS_TOOLTIP_POSITION[currentLayout] || 'top';
|
||||
export function getIndicatorsTooltipPosition(thumbnailType: string) {
|
||||
return INDICATORS_TOOLTIP_POSITION[thumbnailType] || 'top';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -599,7 +601,7 @@ export function isFilmstripResizable(state: Object) {
|
|||
const _currentLayout = getCurrentLayout(state);
|
||||
|
||||
return !filmstrip?.disableResizable && !isMobileBrowser()
|
||||
&& _currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW;
|
||||
&& (_currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW || _currentLayout === LAYOUTS.STAGE_FILMSTRIP_VIEW);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -665,7 +667,8 @@ export function isFilmstripScrollVisible(state) {
|
|||
case LAYOUTS.TILE_VIEW:
|
||||
({ hasScroll = false } = state['features/filmstrip'].tileViewDimensions);
|
||||
break;
|
||||
case LAYOUTS.VERTICAL_FILMSTRIP_VIEW: {
|
||||
case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
|
||||
case LAYOUTS.STAGE_FILMSTRIP_VIEW: {
|
||||
({ hasScroll = false } = state['features/filmstrip'].verticalViewDimensions);
|
||||
break;
|
||||
}
|
||||
|
@ -703,21 +706,30 @@ export function getPinnedActiveParticipants(state) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get whether or not the stage filmstrip should be displayed.
|
||||
* Get whether or not the stage filmstrip is available (enabled & can be used).
|
||||
*
|
||||
* @param {Object} state - Redux state.
|
||||
* @param {number} minParticipantCount - The min number of participants for the stage filmstrip
|
||||
* to be displayed.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function shouldDisplayStageFilmstrip(state, minParticipantCount = 2) {
|
||||
export function isStageFilmstripAvailable(state, minParticipantCount = 0) {
|
||||
const { activeParticipants } = state['features/filmstrip'];
|
||||
const { remoteScreenShares } = state['features/video-layout'];
|
||||
const currentLayout = getCurrentLayout(state);
|
||||
const sharedVideo = isSharingStatus(state['features/shared-video']?.status);
|
||||
|
||||
return isStageFilmstripEnabled(state) && remoteScreenShares.length === 0 && !sharedVideo
|
||||
&& activeParticipants.length >= minParticipantCount && currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW;
|
||||
&& activeParticipants.length >= minParticipantCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether or not the stage filmstrip should be displayed.
|
||||
*
|
||||
* @param {Object} state - Redux state.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function shouldDisplayStageFilmstrip(state) {
|
||||
return isStageFilmstripAvailable(state, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -731,3 +743,27 @@ export function isStageFilmstripEnabled(state) {
|
|||
|
||||
return !(filmstrip?.disableStageFilmstrip ?? true) && interfaceConfig.VERTICAL_FILMSTRIP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the thumbnail type by filmstrip type.
|
||||
*
|
||||
* @param {string} currentLayout - Current app layout.
|
||||
* @param {boolean} isStageFilmstrip - Whether the filmstrip is stage filmstrip or not.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getThumbnailTypeFromLayout(currentLayout, isStageFilmstrip = false) {
|
||||
switch (currentLayout) {
|
||||
case LAYOUTS.TILE_VIEW:
|
||||
return THUMBNAIL_TYPE.TILE;
|
||||
case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
|
||||
return THUMBNAIL_TYPE.VERTICAL;
|
||||
case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW:
|
||||
return THUMBNAIL_TYPE.HORIZONTAL;
|
||||
case LAYOUTS.STAGE_FILMSTRIP_VIEW:
|
||||
if (isStageFilmstrip) {
|
||||
return THUMBNAIL_TYPE.TILE;
|
||||
}
|
||||
|
||||
return THUMBNAIL_TYPE.VERTICAL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
|
||||
import {
|
||||
ADD_STAGE_PARTICIPANT,
|
||||
CLEAR_STAGE_PARTICIPANTS,
|
||||
REMOVE_STAGE_PARTICIPANT,
|
||||
SET_MAX_STAGE_PARTICIPANTS,
|
||||
SET_USER_FILMSTRIP_WIDTH,
|
||||
|
@ -42,10 +43,12 @@ import {
|
|||
import {
|
||||
isFilmstripResizable,
|
||||
updateRemoteParticipants,
|
||||
updateRemoteParticipantsOnLeave
|
||||
updateRemoteParticipantsOnLeave,
|
||||
getActiveParticipantsIds,
|
||||
getPinnedActiveParticipants,
|
||||
isStageFilmstripAvailable
|
||||
} from './functions';
|
||||
import './subscriber';
|
||||
import { getActiveParticipantsIds, getPinnedActiveParticipants, isStageFilmstripEnabled } from './functions.web';
|
||||
|
||||
/**
|
||||
* Map of timers.
|
||||
|
@ -202,15 +205,15 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
case DOMINANT_SPEAKER_CHANGED: {
|
||||
const { id } = action.participant;
|
||||
const state = store.getState();
|
||||
const stageFilmstrip = isStageFilmstripEnabled(state);
|
||||
const currentLayout = getCurrentLayout(state);
|
||||
const stageFilmstrip = isStageFilmstripAvailable(state);
|
||||
const local = getLocalParticipant(state);
|
||||
const currentLayout = getCurrentLayout(state);
|
||||
|
||||
if (id === local.id) {
|
||||
if (id === local.id || currentLayout === LAYOUTS.TILE_VIEW) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (stageFilmstrip && currentLayout === LAYOUTS.VERTICAL_FILMSTRIP_VIEW) {
|
||||
if (stageFilmstrip) {
|
||||
const isPinned = getPinnedActiveParticipants(state).some(p => p.participantId === id);
|
||||
|
||||
store.dispatch(addStageParticipant(id, Boolean(isPinned)));
|
||||
|
@ -276,7 +279,17 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
} else {
|
||||
dispatch(addStageParticipant(participantId, true));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CLEAR_STAGE_PARTICIPANTS: {
|
||||
const activeParticipants = getActiveParticipantsIds(store.getState());
|
||||
|
||||
activeParticipants.forEach(pId => {
|
||||
const tid = timers.get(pId);
|
||||
|
||||
clearTimeout(tid);
|
||||
timers.delete(pId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,8 @@ import {
|
|||
SET_VERTICAL_VIEW_DIMENSIONS,
|
||||
SET_VISIBLE_REMOTE_PARTICIPANTS,
|
||||
SET_VOLUME,
|
||||
SET_MAX_STAGE_PARTICIPANTS
|
||||
SET_MAX_STAGE_PARTICIPANTS,
|
||||
CLEAR_STAGE_PARTICIPANTS
|
||||
} from './actionTypes';
|
||||
|
||||
const DEFAULT_STATE = {
|
||||
|
@ -273,6 +274,12 @@ ReducerRegistry.register(
|
|||
maxStageParticipants: action.maxParticipants
|
||||
};
|
||||
}
|
||||
case CLEAR_STAGE_PARTICIPANTS: {
|
||||
return {
|
||||
...state,
|
||||
activeParticipants: []
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import { isMobileBrowser } from '../base/environment/utils';
|
||||
import { getParticipantCountWithFake } from '../base/participants';
|
||||
import { getParticipantCountWithFake, pinParticipant } from '../base/participants';
|
||||
import { StateListenerRegistry } from '../base/redux';
|
||||
import { clientResized } from '../base/responsive-ui';
|
||||
import { shouldHideSelfView } from '../base/settings';
|
||||
|
@ -17,6 +17,7 @@ import {
|
|||
setTileViewDimensions,
|
||||
setVerticalViewDimensions
|
||||
} from './actions';
|
||||
import { clearStageParticipants } from './actions.web';
|
||||
import {
|
||||
ASPECT_RATIO_BREAKPOINT,
|
||||
DISPLAY_DRAWER_THRESHOLD
|
||||
|
@ -24,7 +25,6 @@ import {
|
|||
import {
|
||||
isFilmstripResizable,
|
||||
isFilmstripScrollVisible,
|
||||
shouldDisplayStageFilmstrip,
|
||||
updateRemoteParticipants
|
||||
} from './functions';
|
||||
|
||||
|
@ -74,6 +74,12 @@ StateListenerRegistry.register(
|
|||
break;
|
||||
case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
|
||||
store.dispatch(setVerticalViewDimensions());
|
||||
if (store.getState()['features/filmstrip'].activeParticipants.length > 1) {
|
||||
store.dispatch(clearStageParticipants());
|
||||
}
|
||||
break;
|
||||
case LAYOUTS.STAGE_FILMSTRIP_VIEW:
|
||||
store.dispatch(pinParticipant(null));
|
||||
break;
|
||||
}
|
||||
}, {
|
||||
|
@ -177,7 +183,7 @@ StateListenerRegistry.register(
|
|||
};
|
||||
},
|
||||
/* listener */(_, store) => {
|
||||
if (shouldDisplayStageFilmstrip(store.getState())) {
|
||||
if (getCurrentLayout(store.getState()) === LAYOUTS.STAGE_FILMSTRIP_VIEW) {
|
||||
store.dispatch(setStageFilmstripViewDimensions());
|
||||
}
|
||||
}, {
|
||||
|
|
|
@ -9,7 +9,8 @@ import {
|
|||
getPinnedParticipant,
|
||||
getRemoteParticipants
|
||||
} from '../base/participants';
|
||||
import { isStageFilmstripEnabled } from '../filmstrip/functions';
|
||||
import { isStageFilmstripAvailable } from '../filmstrip/functions';
|
||||
import { shouldDisplayStageFilmstrip } from '../filmstrip/functions.web';
|
||||
|
||||
import {
|
||||
SELECT_LARGE_VIDEO_PARTICIPANT,
|
||||
|
@ -30,6 +31,10 @@ export function selectParticipantInLargeVideo(participant: ?string) {
|
|||
return (dispatch: Dispatch<any>, getState: Function) => {
|
||||
const state = getState();
|
||||
|
||||
if (shouldDisplayStageFilmstrip(state)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep Etherpad open.
|
||||
if (state['features/etherpad'].editing) {
|
||||
return;
|
||||
|
@ -103,7 +108,7 @@ function _electLastVisibleRemoteVideo(tracks) {
|
|||
* @returns {(string|undefined)}
|
||||
*/
|
||||
function _electParticipantInLargeVideo(state) {
|
||||
const stageFilmstrip = isStageFilmstripEnabled(state);
|
||||
const stageFilmstrip = isStageFilmstripAvailable(state);
|
||||
let participant;
|
||||
|
||||
if (!stageFilmstrip) {
|
||||
|
|
|
@ -6,5 +6,6 @@
|
|||
export const LAYOUTS = {
|
||||
HORIZONTAL_FILMSTRIP_VIEW: 'horizontal-filmstrip-view',
|
||||
TILE_VIEW: 'tile-view',
|
||||
VERTICAL_FILMSTRIP_VIEW: 'vertical-filmstrip-view'
|
||||
VERTICAL_FILMSTRIP_VIEW: 'vertical-filmstrip-view',
|
||||
STAGE_FILMSTRIP_VIEW: 'stage-filmstrip-view'
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
getParticipantCount,
|
||||
pinParticipant
|
||||
} from '../base/participants';
|
||||
import { shouldDisplayStageFilmstrip } from '../filmstrip/functions.web';
|
||||
import { isVideoPlaying } from '../shared-video/functions';
|
||||
import { VIDEO_QUALITY_LEVELS } from '../video-quality/constants';
|
||||
|
||||
|
@ -40,6 +41,10 @@ export function getCurrentLayout(state: Object) {
|
|||
if (shouldDisplayTileView(state)) {
|
||||
return LAYOUTS.TILE_VIEW;
|
||||
} else if (interfaceConfig.VERTICAL_FILMSTRIP) {
|
||||
if (shouldDisplayStageFilmstrip(state)) {
|
||||
return LAYOUTS.STAGE_FILMSTRIP_VIEW;
|
||||
}
|
||||
|
||||
return LAYOUTS.VERTICAL_FILMSTRIP_VIEW;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ import { setParticipantContextMenuOpen } from '../../../base/responsive-ui/actio
|
|||
import { getHideSelfView } from '../../../base/settings';
|
||||
import { getLocalVideoTrack } from '../../../base/tracks';
|
||||
import ConnectionIndicatorContent from '../../../connection-indicator/components/web/ConnectionIndicatorContent';
|
||||
import { THUMBNAIL_TYPE } from '../../../filmstrip';
|
||||
import { isStageFilmstripEnabled } from '../../../filmstrip/functions.web';
|
||||
import { LAYOUTS } from '../../../video-layout';
|
||||
import { renderConnectionStatus } from '../../actions.web';
|
||||
|
||||
import ConnectionStatusButton from './ConnectionStatusButton';
|
||||
|
@ -274,7 +274,7 @@ class LocalVideoMenuTriggerButton extends Component<Props> {
|
|||
* @returns {Props}
|
||||
*/
|
||||
function _mapStateToProps(state, ownProps) {
|
||||
const { currentLayout } = ownProps;
|
||||
const { thumbnailType } = ownProps;
|
||||
const localParticipant = getLocalParticipant(state);
|
||||
const { disableLocalVideoFlip, disableSelfViewSettings } = state['features/base/config'];
|
||||
const videoTrack = getLocalVideoTrack(state['features/base/tracks']);
|
||||
|
@ -284,14 +284,14 @@ function _mapStateToProps(state, ownProps) {
|
|||
|
||||
let _menuPosition;
|
||||
|
||||
switch (currentLayout) {
|
||||
case LAYOUTS.TILE_VIEW:
|
||||
switch (thumbnailType) {
|
||||
case THUMBNAIL_TYPE.TILE:
|
||||
_menuPosition = 'left-start';
|
||||
break;
|
||||
case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
|
||||
case THUMBNAIL_TYPE.VERTICAL:
|
||||
_menuPosition = 'left-start';
|
||||
break;
|
||||
case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW:
|
||||
case THUMBNAIL_TYPE.HORIZONTAL:
|
||||
_menuPosition = 'top-start';
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -14,7 +14,7 @@ import { getParticipantById } from '../../../base/participants';
|
|||
import { Popover } from '../../../base/popover';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { setParticipantContextMenuOpen } from '../../../base/responsive-ui/actions';
|
||||
import { LAYOUTS } from '../../../video-layout';
|
||||
import { THUMBNAIL_TYPE } from '../../../filmstrip';
|
||||
import { renderConnectionStatus } from '../../actions.web';
|
||||
|
||||
import ParticipantContextMenu from './ParticipantContextMenu';
|
||||
|
@ -265,7 +265,7 @@ class RemoteVideoMenuTriggerButton extends Component<Props> {
|
|||
* @returns {Props}
|
||||
*/
|
||||
function _mapStateToProps(state, ownProps) {
|
||||
const { participantID, currentLayout } = ownProps;
|
||||
const { participantID, thumbnailType } = ownProps;
|
||||
let _remoteControlState = null;
|
||||
const participant = getParticipantById(state, participantID);
|
||||
const _participantDisplayName = participant?.name;
|
||||
|
@ -291,14 +291,14 @@ function _mapStateToProps(state, ownProps) {
|
|||
|
||||
let _menuPosition;
|
||||
|
||||
switch (currentLayout) {
|
||||
case LAYOUTS.TILE_VIEW:
|
||||
switch (thumbnailType) {
|
||||
case THUMBNAIL_TYPE.TILE:
|
||||
_menuPosition = 'left-start';
|
||||
break;
|
||||
case LAYOUTS.VERTICAL_FILMSTRIP_VIEW:
|
||||
case THUMBNAIL_TYPE.VERTICAL:
|
||||
_menuPosition = 'left-end';
|
||||
break;
|
||||
case LAYOUTS.HORIZONTAL_FILMSTRIP_VIEW:
|
||||
case THUMBNAIL_TYPE.HORIZONTAL:
|
||||
_menuPosition = 'top';
|
||||
break;
|
||||
default:
|
||||
|
|
Loading…
Reference in New Issue