feat: Drops filmStripOnly mode. (#8074)

* feat: Drops filmStripOnly mode.

* squash: Let's make lint happy again.

* squash: Drop some css.
This commit is contained in:
Дамян Минков 2020-11-10 16:21:07 -06:00 committed by GitHub
parent f6127d45e9
commit 12c835dd91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 45 additions and 713 deletions

View File

@ -28,9 +28,6 @@ body {
overflow: hidden; overflow: hidden;
color: $defaultColor; color: $defaultColor;
background: $defaultBackground; background: $defaultBackground;
&.filmstrip-only {
background: transparent;
}
} }
/** /**
@ -70,16 +67,6 @@ body {
cursor: pointer; cursor: pointer;
} }
/**
* AtlasKitThemeProvider sets a background color on an app-wrapping div, thereby
* preventing transparency in filmstrip-only mode. The selector chosen to
* override this behavior is specific to where the AtlasKitThemeProvider might
* be placed within the app hierarchy.
*/
.filmstrip-only #react > .ckAJgx {
background: transparent;
}
p { p {
margin: 0; margin: 0;
} }

View File

@ -27,84 +27,4 @@
font-size: 50px; font-size: 50px;
} }
&-filmstrip-only {
background-color: $inlayFilmstripOnlyBg;
color: $inlayFilmstripOnlyColor;
margin-left: 20px;
margin-right: 20px;
margin-top: 20px;
bottom: 30px;
position: absolute;
display: flex;
max-height: 120px;
height: 80%;
right: 0px;
border-radius: 4px;
overflow: hidden;
&__content {
padding: 20px;
display: flex;
justify-content: center;
position: relative;
> .button-control {
align-self: center;
}
> #reloadProgressBar {
position: absolute;
left: 0px;
bottom: 0px;
margin-bottom: 0px;
width: 100%;
border-radius: 0px;
}
}
&__title {
font-size: 18px;
font-weight: 600;
}
&__container {
align-self: center;
}
&__text {
margin-top: 10px;
font-size: 14px;
font-weight: 600;
}
&__icon {
font-size: 50px;
align-self: center;
color: $inlayIconColor;
opacity: 0.6;
}
&__icon-container {
text-align: center;
display: flex;
justify-content: center;
position: absolute;
width: 100%;
height: 100%;
top: 0px;
}
&__avatar-container {
height: 100%;
position: relative;
> img {
height: 100%;
}
}
&__icon-background {
background: $inlayIconBg;
opacity: 0.6;
position: absolute;
width: 100%;
height: 100%;
top: 0px;
}
}
} }

View File

@ -67,20 +67,6 @@
} }
} }
/**
* Style the filmstrip videos in filmstrip-only mode.
*/
&__videos-filmstripOnly {
margin-top: auto;
margin-bottom: auto;
.filmstrip__videos {
&#filmstripLocalVideo {
bottom: 0px;
}
}
}
.remote-videos-container { .remote-videos-container {
transition: opacity 1s; transition: opacity 1s;
} }

View File

@ -145,26 +145,6 @@
} }
} }
/**
* Override other styles to support vertical filmstrip mode.
*/
.filmstrip-only .vertical-filmstrip {
.filmstrip {
flex-direction: row-reverse;
}
.filmstrip__videos-filmstripOnly {
margin-top: auto;
margin-bottom: auto;
height: 100%;
}
.filmstrip__videos {
&#filmstripLocalVideo {
bottom: 0px;
}
}
}
/** /**
* Workarounds for Edge and Firefox not handling scrolling properly with * Workarounds for Edge and Firefox not handling scrolling properly with
* flex-direction: column-reverse. The remove videos in filmstrip should * flex-direction: column-reverse. The remove videos in filmstrip should

View File

@ -8,16 +8,10 @@
position: fixed; position: fixed;
z-index: $overlayZ; z-index: $overlayZ;
background: $defaultBackground; background: $defaultBackground;
&.filmstrip-only {
@include transparentBg($filmstripOnlyOverlayBg, 0.8);
}
} }
&__container-light { &__container-light {
@include transparentBg($defaultBackground, 0.7); @include transparentBg($defaultBackground, 0.7);
&.filmstrip-only {
@include transparentBg($filmstripOnlyOverlayBg, 0.2);
}
} }
&__content { &__content {
@ -27,11 +21,6 @@
width: 56%; width: 56%;
left: 50%; left: 50%;
@include transform(translateX(-50%)); @include transform(translateX(-50%));
&.filmstrip-only {
left: 0px;
width: 100%;
@include transform(none);
}
&_bottom { &_bottom {
position: absolute; position: absolute;

View File

@ -41,7 +41,6 @@ $overlayButtonBg: #0074E0;
* Color variables * Color variables
**/ **/
$defaultBackground: #474747; $defaultBackground: #474747;
$filmstripOnlyOverlayBg: #000;
$reloadProgressBarBg: #0074E0; $reloadProgressBarBg: #0074E0;
/** /**
@ -59,10 +58,6 @@ $dialogErrorText: #344563;
**/ **/
$inlayColorBg: lighten($defaultBackground, 20%); $inlayColorBg: lighten($defaultBackground, 20%);
$inlayBorderColor: lighten($baseLight, 10%); $inlayBorderColor: lighten($baseLight, 10%);
$inlayIconBg: #000;
$inlayIconColor: #fff;
$inlayFilmstripOnlyColor: #474747;
$inlayFilmstripOnlyBg: #fff;
// Main controls // Main controls
$placeHolderColor: #a7a7a7; $placeHolderColor: #a7a7a7;

View File

@ -13,9 +13,7 @@
height: 180, height: 180,
parentNode: undefined, parentNode: undefined,
configOverwrite: {}, configOverwrite: {},
interfaceConfigOverwrite: { interfaceConfigOverwrite: {}
filmStripOnly: true
}
} }
var api = new JitsiMeetExternalAPI(domain, options); var api = new JitsiMeetExternalAPI(domain, options);
</script> </script>

View File

@ -97,11 +97,6 @@ var interfaceConfig = {
FILM_STRIP_MAX_HEIGHT: 120, FILM_STRIP_MAX_HEIGHT: 120,
/**
* Whether to only show the filmstrip (and hide the toolbar).
*/
filmStripOnly: false,
GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true, GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true,
/** /**

View File

@ -1,4 +1,4 @@
/* global APP, $, config, interfaceConfig */ /* global APP, $, config */
const UI = {}; const UI = {};
@ -143,9 +143,7 @@ UI.start = function() {
$.prompt.setDefaults({ persistent: false }); $.prompt.setDefaults({ persistent: false });
VideoLayout.init(eventEmitter); VideoLayout.init(eventEmitter);
if (!interfaceConfig.filmStripOnly) { VideoLayout.initLargeVideo();
VideoLayout.initLargeVideo();
}
// Do not animate the video area on UI start (second argument passed into // Do not animate the video area on UI start (second argument passed into
// resizeVideoArea) because the animation is not visible anyway. Plus with // resizeVideoArea) because the animation is not visible anyway. Plus with
@ -161,10 +159,7 @@ UI.start = function() {
$('body').addClass('desktop-browser'); $('body').addClass('desktop-browser');
} }
if (interfaceConfig.filmStripOnly) { if (config.iAmRecorder) {
$('body').addClass('filmstrip-only');
APP.store.dispatch(setNotificationsEnabled(false));
} else if (config.iAmRecorder) {
// in case of iAmSipGateway keep local video visible // in case of iAmSipGateway keep local video visible
if (!config.iAmSipGateway) { if (!config.iAmSipGateway) {
VideoLayout.setLocalVideoVisible(false); VideoLayout.setLocalVideoVisible(false);

View File

@ -135,10 +135,6 @@ export default class RemoteVideo extends SmallVideo {
* @private * @private
*/ */
_generatePopupContent() { _generatePopupContent() {
if (interfaceConfig.filmStripOnly) {
return;
}
const remoteVideoMenuContainer const remoteVideoMenuContainer
= this.container.querySelector('.remotevideomenu'); = this.container.querySelector('.remotevideomenu');

View File

@ -699,7 +699,7 @@ export default class SmallVideo {
alwaysVisible = { showConnectionIndicator } alwaysVisible = { showConnectionIndicator }
iconSize = { iconSize } iconSize = { iconSize }
isLocalVideo = { this.isLocal } isLocalVideo = { this.isLocal }
enableStatsDisplay = { !interfaceConfig.filmStripOnly } enableStatsDisplay = { true }
participantId = { this.id } participantId = { this.id }
statsPopoverPosition = { statsPopoverPosition } /> statsPopoverPosition = { statsPopoverPosition } />
: null } : null }

View File

@ -1,4 +1,4 @@
/* global APP, $, interfaceConfig */ /* global APP, $ */
import Logger from 'jitsi-meet-logger'; import Logger from 'jitsi-meet-logger';
@ -264,10 +264,6 @@ const VideoLayout = {
* @returns {void} * @returns {void}
*/ */
onPinChange(pinnedParticipantID) { onPinChange(pinnedParticipantID) {
if (interfaceConfig.filmStripOnly) {
return;
}
getAllThumbnails().forEach(thumbnail => getAllThumbnails().forEach(thumbnail =>
thumbnail.focus(pinnedParticipantID === thumbnail.getId())); thumbnail.focus(pinnedParticipantID === thumbnail.getId()));
}, },

View File

@ -1,4 +1,4 @@
/* global APP, $, interfaceConfig */ /* global APP, $ */
import Logger from 'jitsi-meet-logger'; import Logger from 'jitsi-meet-logger';
@ -203,14 +203,12 @@ const KeyboardShortcut = {
}); });
this._addShortcutToHelp('SPACE', 'keyboardShortcuts.pushToTalk'); this._addShortcutToHelp('SPACE', 'keyboardShortcuts.pushToTalk');
if (!interfaceConfig.filmStripOnly) { this.registerShortcut('T', null, () => {
this.registerShortcut('T', null, () => { sendAnalytics(createShortcutEvent('speaker.stats'));
sendAnalytics(createShortcutEvent('speaker.stats')); APP.store.dispatch(toggleDialog(SpeakerStats, {
APP.store.dispatch(toggleDialog(SpeakerStats, { conference: APP.conference
conference: APP.conference }));
})); }, 'keyboardShortcuts.showSpeakerStats');
}, 'keyboardShortcuts.showSpeakerStats');
}
/** /**
* FIXME: Currently focus keys are directly implemented below in * FIXME: Currently focus keys are directly implemented below in

View File

@ -54,6 +54,5 @@ export default [
'UNSUPPORTED_BROWSERS', 'UNSUPPORTED_BROWSERS',
'VERTICAL_FILMSTRIP', 'VERTICAL_FILMSTRIP',
'VIDEO_LAYOUT_FIT', 'VIDEO_LAYOUT_FIT',
'VIDEO_QUALITY_LABEL_DISABLED', 'VIDEO_QUALITY_LABEL_DISABLED'
'filmStripOnly'
]; ];

View File

@ -84,13 +84,7 @@ class Watermarks extends Component<Props, State> {
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
let showBrandWatermark; const showBrandWatermark = interfaceConfig.SHOW_BRAND_WATERMARK;
if (interfaceConfig.filmStripOnly) {
showBrandWatermark = false;
} else {
showBrandWatermark = interfaceConfig.SHOW_BRAND_WATERMARK;
}
this.state = { this.state = {
brandWatermarkLink: brandWatermarkLink:
@ -237,12 +231,11 @@ function _mapStateToProps(state, ownProps) {
const { const {
DEFAULT_LOGO_URL, DEFAULT_LOGO_URL,
JITSI_WATERMARK_LINK, JITSI_WATERMARK_LINK,
SHOW_JITSI_WATERMARK, SHOW_JITSI_WATERMARK
filmStripOnly
} = interfaceConfig; } = interfaceConfig;
let _showJitsiWatermark = (!filmStripOnly let _showJitsiWatermark = (
&& (customizationReady && !customizationFailed) customizationReady && !customizationFailed
&& SHOW_JITSI_WATERMARK) && SHOW_JITSI_WATERMARK)
|| !isValidRoom; || !isValidRoom;
let _logoUrl = logoImageUrl; let _logoUrl = logoImageUrl;
let _logoLink = logoClickUrl; let _logoLink = logoClickUrl;

View File

@ -152,11 +152,9 @@ StateListenerRegistry.register(
* @returns {void} * @returns {void}
*/ */
function _addChatMsgListener(conference, store) { function _addChatMsgListener(conference, store) {
if ((typeof interfaceConfig === 'object' && interfaceConfig.filmStripOnly) if ((typeof APP !== 'undefined' && !isButtonEnabled('chat'))
|| (typeof APP !== 'undefined' && !isButtonEnabled('chat'))
|| store.getState()['features/base/config'].iAmRecorder) { || store.getState()['features/base/config'].iAmRecorder) {
// We don't register anything on web if we're in filmStripOnly mode, or // We don't register anything on web if the chat button is not enabled in interfaceConfig
// the chat button is not enabled in interfaceConfig.
// or we are in iAmRecorder mode // or we are in iAmRecorder mode
return; return;
} }

View File

@ -14,7 +14,7 @@ import { CalleeInfoContainer } from '../../../invite';
import { LargeVideo } from '../../../large-video'; import { LargeVideo } from '../../../large-video';
import { KnockingParticipantList, LobbyScreen } from '../../../lobby'; import { KnockingParticipantList, LobbyScreen } from '../../../lobby';
import { Prejoin, isPrejoinPageVisible } from '../../../prejoin'; import { Prejoin, isPrejoinPageVisible } from '../../../prejoin';
import { fullScreenChanged, setToolboxAlwaysVisible, showToolbox } from '../../../toolbox/actions.web'; import { fullScreenChanged, showToolbox } from '../../../toolbox/actions.web';
import { Toolbox } from '../../../toolbox/components/web'; import { Toolbox } from '../../../toolbox/components/web';
import { LAYOUTS, getCurrentLayout } from '../../../video-layout'; import { LAYOUTS, getCurrentLayout } from '../../../video-layout';
import { maybeShowSuboptimalExperienceNotification } from '../../functions'; import { maybeShowSuboptimalExperienceNotification } from '../../functions';
@ -28,7 +28,6 @@ import Labels from './Labels';
import { default as Notice } from './Notice'; import { default as Notice } from './Notice';
declare var APP: Object; declare var APP: Object;
declare var config: Object;
declare var interfaceConfig: Object; declare var interfaceConfig: Object;
/** /**
@ -175,18 +174,13 @@ class Conference extends AbstractConference<Props, *> {
* @returns {ReactElement} * @returns {ReactElement}
*/ */
render() { render() {
const {
// XXX The character casing of the name filmStripOnly utilized by
// interfaceConfig is obsolete but legacy support is required.
filmStripOnly: filmstripOnly
} = interfaceConfig;
const { const {
_iAmRecorder, _iAmRecorder,
_isLobbyScreenVisible, _isLobbyScreenVisible,
_layoutClassName, _layoutClassName,
_showPrejoin _showPrejoin
} = this.props; } = this.props;
const hideLabels = filmstripOnly || _iAmRecorder; const hideLabels = _iAmRecorder;
return ( return (
<div <div
@ -198,18 +192,18 @@ class Conference extends AbstractConference<Props, *> {
<div id = 'videospace'> <div id = 'videospace'>
<LargeVideo /> <LargeVideo />
<KnockingParticipantList /> <KnockingParticipantList />
<Filmstrip filmstripOnly = { filmstripOnly } /> <Filmstrip />
{ hideLabels || <Labels /> } { hideLabels || <Labels /> }
</div> </div>
{ filmstripOnly || _showPrejoin || _isLobbyScreenVisible || <Toolbox /> } { _showPrejoin || _isLobbyScreenVisible || <Toolbox /> }
{ filmstripOnly || <Chat /> } <Chat />
{ this.renderNotificationsContainer() } { this.renderNotificationsContainer() }
<CalleeInfoContainer /> <CalleeInfoContainer />
{ !filmstripOnly && _showPrejoin && <Prejoin />} { _showPrejoin && <Prejoin />}
</div> </div>
); );
} }
@ -256,9 +250,6 @@ class Conference extends AbstractConference<Props, *> {
dispatch(connect()); dispatch(connect());
maybeShowSuboptimalExperienceNotification(dispatch, t); maybeShowSuboptimalExperienceNotification(dispatch, t);
interfaceConfig.filmStripOnly
&& dispatch(setToolboxAlwaysVisible(true));
} }
} }

View File

@ -56,7 +56,7 @@ export function maybeOpenFeedbackDialog(conference: Object) {
const state = getState(); const state = getState();
const { feedbackPercentage = 100 } = state['features/base/config']; const { feedbackPercentage = 100 } = state['features/base/config'];
if (interfaceConfig.filmStripOnly || config.iAmRecorder) { if (config.iAmRecorder) {
// Intentionally fall through the if chain to prevent further action // Intentionally fall through the if chain to prevent further action
// from being taken with regards to showing feedback. // from being taken with regards to showing feedback.
} else if (state['features/base/dialog'].component === FeedbackDialog) { } else if (state['features/base/dialog'].component === FeedbackDialog) {

View File

@ -17,8 +17,6 @@ import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
import { setFilmstripHovered, setFilmstripVisible } from '../../actions'; import { setFilmstripHovered, setFilmstripVisible } from '../../actions';
import { shouldRemoteVideosBeVisible } from '../../functions'; import { shouldRemoteVideosBeVisible } from '../../functions';
import Toolbar from './Toolbar';
declare var APP: Object; declare var APP: Object;
declare var interfaceConfig: Object; declare var interfaceConfig: Object;
@ -42,11 +40,6 @@ type Props = {
*/ */
_columns: number, _columns: number,
/**
* Whether the UI/UX is filmstrip-only.
*/
_filmstripOnly: boolean,
/** /**
* The width of the filmstrip. * The width of the filmstrip.
*/ */
@ -142,14 +135,12 @@ class Filmstrip extends Component <Props> {
* @inheritdoc * @inheritdoc
*/ */
componentDidMount() { componentDidMount() {
if (!this.props._filmstripOnly) { APP.keyboardshortcut.registerShortcut(
APP.keyboardshortcut.registerShortcut( 'F',
'F', 'filmstripPopover',
'filmstripPopover', this._onShortcutToggleFilmstrip,
this._onShortcutToggleFilmstrip, 'keyboardShortcuts.toggleFilmstrip'
'keyboardShortcuts.toggleFilmstrip' );
);
}
} }
/** /**
@ -207,7 +198,7 @@ class Filmstrip extends Component <Props> {
let toolbar = null; let toolbar = null;
if (!this.props._hideToolbar) { if (!this.props._hideToolbar) {
toolbar = this.props._filmstripOnly ? <Toolbar /> : this._renderToggleButton(); toolbar = this._renderToggleButton();
} }
return ( return (
@ -367,24 +358,20 @@ class Filmstrip extends Component <Props> {
function _mapStateToProps(state) { function _mapStateToProps(state) {
const { iAmSipGateway } = state['features/base/config']; const { iAmSipGateway } = state['features/base/config'];
const { hovered, visible } = state['features/filmstrip']; const { hovered, visible } = state['features/filmstrip'];
const isFilmstripOnly = Boolean(interfaceConfig.filmStripOnly);
const reduceHeight const reduceHeight
= !isFilmstripOnly && state['features/toolbox'].visible && interfaceConfig.TOOLBAR_BUTTONS.length; = state['features/toolbox'].visible && interfaceConfig.TOOLBAR_BUTTONS.length;
const remoteVideosVisible = shouldRemoteVideosBeVisible(state); const remoteVideosVisible = shouldRemoteVideosBeVisible(state);
const { isOpen: shiftRight } = state['features/chat']; const { isOpen: shiftRight } = state['features/chat'];
const className = `${remoteVideosVisible ? '' : 'hide-videos'} ${ const className = `${remoteVideosVisible ? '' : 'hide-videos'} ${
reduceHeight ? 'reduce-height' : '' reduceHeight ? 'reduce-height' : ''
} ${shiftRight ? 'shift-right' : ''}`.trim(); } ${shiftRight ? 'shift-right' : ''}`.trim();
const videosClassName = `filmstrip__videos${ const videosClassName = `filmstrip__videos${visible ? '' : ' hidden'}`;
isFilmstripOnly ? ' filmstrip__videos-filmstripOnly' : ''}${
visible ? '' : ' hidden'}`;
const { gridDimensions = {}, filmstripWidth } = state['features/filmstrip'].tileViewDimensions; const { gridDimensions = {}, filmstripWidth } = state['features/filmstrip'].tileViewDimensions;
return { return {
_className: className, _className: className,
_columns: gridDimensions.columns, _columns: gridDimensions.columns,
_currentLayout: getCurrentLayout(state), _currentLayout: getCurrentLayout(state),
_filmstripOnly: isFilmstripOnly,
_filmstripWidth: filmstripWidth, _filmstripWidth: filmstripWidth,
_hideScrollbar: Boolean(iAmSipGateway), _hideScrollbar: Boolean(iAmSipGateway),
_hideToolbar: Boolean(iAmSipGateway), _hideToolbar: Boolean(iAmSipGateway),

View File

@ -1,101 +0,0 @@
// @flow
import React, { Component } from 'react';
import { connect, equals } from '../../../base/redux';
import { SettingsButton } from '../../../settings';
import {
AudioMuteButton,
HangupButton,
VideoMuteButton
} from '../../../toolbox/components';
declare var interfaceConfig: Object;
// XXX: We are not currently using state here, but in the future, when
// interfaceConfig is part of redux we will. This has to be retrieved from the store.
const visibleButtons = new Set(interfaceConfig.TOOLBAR_BUTTONS);
/**
* The type of the React {@code Component} props of {@link Toolbar}.
*/
type Props = {
/**
* The set of buttons which should be visible in this {@code Toolbar}.
*/
_visibleButtons: Set<string>
};
/**
* Implements the conference toolbar on React/Web for filmstrip-only mode.
*
* @extends Component
*/
class Toolbar extends Component<Props> {
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
return (
<div
className = 'filmstrip-toolbox'
id = 'new-toolbox'>
<HangupButton
tooltipPosition = 'left'
visible = { this._shouldShowButton('hangup') } />
<AudioMuteButton
tooltipPosition = 'left'
visible = { this._shouldShowButton('microphone') } />
<VideoMuteButton
tooltipPosition = 'left'
visible = { this._shouldShowButton('camera') } />
<SettingsButton
tooltipPosition = 'left'
visible = { this._shouldShowButton('fodeviceselection') } />
</div>
);
}
_shouldShowButton: (string) => boolean;
/**
* Returns if a button name has been explicitly configured to be displayed.
*
* @param {string} buttonName - The name of the button, as expected in
* {@link intefaceConfig}.
* @private
* @returns {boolean} True if the button should be displayed, false
* otherwise.
*/
_shouldShowButton(buttonName) {
return this.props._visibleButtons.has(buttonName);
}
}
/**
* Maps (parts of) the redux state to the associated props for this component.
*
* @param {Object} state - The Redux state.
* @private
* @returns {{
* _visibleButtons: Set<string>
* }}
*/
function _mapStateToProps(state): Object { // eslint-disable-line no-unused-vars
// XXX: We are not currently using state here, but in the future, when
// interfaceConfig is part of redux we will.
//
// NB: We compute the buttons again here because if URL parameters were used to
// override them we'd miss it.
const buttons = new Set(interfaceConfig.TOOLBAR_BUTTONS);
return {
_visibleButtons: equals(visibleButtons, buttons) ? visibleButtons : buttons
};
}
export default connect(_mapStateToProps)(Toolbar);

View File

@ -56,9 +56,6 @@ export function shouldRemoteVideosBeVisible(state: Object) {
|| ((pinnedParticipant = getPinnedParticipant(state)) || ((pinnedParticipant = getPinnedParticipant(state))
&& pinnedParticipant.local))) && pinnedParticipant.local)))
|| (typeof interfaceConfig === 'object'
&& interfaceConfig.filmStripOnly)
|| state['features/base/config'].disable1On1Mode); || state['features/base/config'].disable1On1Mode);
} }

View File

@ -1,112 +0,0 @@
// @flow
import React, { Component } from 'react';
import { Avatar } from '../../../base/avatar';
import { getLocalParticipant } from '../../../base/participants';
import { connect } from '../../../base/redux';
import OverlayFrame from './OverlayFrame';
/**
* The type of the React {@code Component} props of
* {@link FilmstripOnlyOverlayFrame}.
*/
type Props = {
/**
* The ID of the local participant.
*/
_localParticipantId: string,
/**
* The children components to be displayed into the overlay frame for
* filmstrip only mode.
*/
children: React$Node,
/**
* The css class name for the icon that will be displayed over the avatar.
*/
icon: string,
/**
* Indicates the css style of the overlay. If true, then lighter; darker,
* otherwise.
*/
isLightOverlay: boolean
};
/**
* Implements a React Component for the frame of the overlays in filmstrip only
* mode.
*/
class FilmstripOnlyOverlayFrame extends Component<Props> {
/**
* Renders content related to the icon.
*
* @returns {ReactElement|null}
* @private
*/
_renderIcon() {
if (!this.props.icon) {
return null;
}
const iconClass = `inlay-filmstrip-only__icon ${this.props.icon}`;
const iconBGClass = 'inlay-filmstrip-only__icon-background';
return (
<div>
<div className = { iconBGClass } />
<div className = 'inlay-filmstrip-only__icon-container'>
<span className = { iconClass } />
</div>
</div>
);
}
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
return (
<OverlayFrame isLightOverlay = { this.props.isLightOverlay }>
<div className = 'inlay-filmstrip-only'>
<div className = 'inlay-filmstrip-only__content'>
{
this.props.children
}
</div>
<div className = 'inlay-filmstrip-only__avatar-container'>
<Avatar participantId = { this.props._localParticipantId } />
{
this._renderIcon()
}
</div>
</div>
</OverlayFrame>
);
}
}
/**
* Maps (parts of) the Redux state to the associated FilmstripOnlyOverlayFrame
* props.
*
* @param {Object} state - The Redux state.
* @private
* @returns {{
* _localParticipantId: string
* }}
*/
function _mapStateToProps(state) {
return {
_localParticipantId: (getLocalParticipant(state) || {}).id
};
}
export default connect(_mapStateToProps)(FilmstripOnlyOverlayFrame);

View File

@ -21,44 +21,10 @@ type Props = {
isLightOverlay?: boolean isLightOverlay?: boolean
}; };
/**
* The type of the React {@code Component} state of {@link OverlayFrame}.
*/
type State = {
/**
* Whether or not the application is currently displaying in filmstrip only
* mode.
*/
filmstripOnly: boolean
};
/** /**
* Implements a React {@link Component} for the frame of the overlays. * Implements a React {@link Component} for the frame of the overlays.
*/ */
export default class OverlayFrame extends Component<Props, State> { export default class OverlayFrame extends Component<Props> {
/**
* Initializes a new AbstractOverlay instance.
*
* @param {Object} props - The read-only properties with which the new
* instance is to be initialized.
* @public
*/
constructor(props: Props) {
super(props);
this.state = {
/**
* Indicates whether the filmstrip only mode is enabled or not.
*
* @type {boolean}
*/
filmstripOnly:
typeof interfaceConfig !== 'undefined'
&& interfaceConfig.filmStripOnly
};
}
/** /**
* Implements React's {@link Component#render()}. * Implements React's {@link Component#render()}.
* *
@ -66,20 +32,11 @@ export default class OverlayFrame extends Component<Props, State> {
* @returns {ReactElement|null} * @returns {ReactElement|null}
*/ */
render() { render() {
let containerClass = this.props.isLightOverlay
? 'overlay__container-light' : 'overlay__container';
let contentClass = 'overlay__content';
if (this.state.filmstripOnly) {
containerClass += ' filmstrip-only';
contentClass += ' filmstrip-only';
}
return ( return (
<div <div
className = { containerClass } className = { this.props.isLightOverlay ? 'overlay__container-light' : 'overlay__container' }
id = 'overlay'> id = 'overlay'>
<div className = { contentClass }> <div className = { 'overlay__content' }>
{ {
this.props.children this.props.children
} }

View File

@ -1,50 +0,0 @@
// @flow
import React from 'react';
import { translate } from '../../../base/i18n';
import { connect } from '../../../base/redux';
import AbstractPageReloadOverlay, { type Props, abstractMapStateToProps }
from '../AbstractPageReloadOverlay';
import FilmstripOnlyOverlayFrame from './FilmstripOnlyOverlayFrame';
/**
* Implements a React Component for page reload overlay for filmstrip only
* mode. Shown before the conference is reloaded. Shows a warning message and
* counts down towards the reload.
*/
class PageReloadFilmstripOnlyOverlay extends AbstractPageReloadOverlay<Props> {
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
const { t } = this.props;
const { message, timeLeft, title } = this.state;
return (
<FilmstripOnlyOverlayFrame>
<div className = 'inlay-filmstrip-only__container'>
<div className = 'inlay-filmstrip-only__title'>
{ t(title) }
</div>
<div className = 'inlay-filmstrip-only__text'>
{ t(message, { seconds: timeLeft }) }
</div>
</div>
{ this._renderButton() }
{ this._renderProgressBar() }
</FilmstripOnlyOverlayFrame>
);
}
_renderButton: () => React$Element<*> | null
_renderProgressBar: () => React$Element<*> | null
}
export default translate(
connect(abstractMapStateToProps)(PageReloadFilmstripOnlyOverlay));

View File

@ -1,41 +0,0 @@
// @flow
import React from 'react';
import { translate, translateToHTML } from '../../../base/i18n';
import AbstractSuspendedOverlay from './AbstractSuspendedOverlay';
import FilmstripOnlyOverlayFrame from './FilmstripOnlyOverlayFrame';
import ReloadButton from './ReloadButton';
/**
* Implements a React Component for suspended overlay for filmstrip only mode.
* Shown when suspended is detected.
*/
class SuspendedFilmstripOnlyOverlay extends AbstractSuspendedOverlay {
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
const { t } = this.props;
return (
<FilmstripOnlyOverlayFrame isLightOverlay = { true }>
<div className = 'inlay-filmstrip-only__container'>
<div className = 'inlay-filmstrip-only__title'>
{ t('suspendedoverlay.title') }
</div>
<div className = 'inlay-filmstrip-only__text'>
{ translateToHTML(t, 'suspendedoverlay.text') }
</div>
</div>
<ReloadButton textKey = 'suspendedoverlay.rejoinKeyTitle' />
</FilmstripOnlyOverlayFrame>
);
}
}
export default translate(SuspendedFilmstripOnlyOverlay);

View File

@ -1,54 +0,0 @@
// @flow
import React from 'react';
import { translate, translateToHTML } from '../../../base/i18n';
import { connect } from '../../../base/redux';
import AbstractUserMediaPermissionsOverlay, { abstractMapStateToProps }
from './AbstractUserMediaPermissionsOverlay';
import FilmstripOnlyOverlayFrame from './FilmstripOnlyOverlayFrame';
declare var interfaceConfig: Object;
/**
* Implements a React Component for overlay with guidance how to proceed with
* gUM prompt. This component will be displayed only for filmstrip only mode.
*/
class UserMediaPermissionsFilmstripOnlyOverlay
extends AbstractUserMediaPermissionsOverlay {
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
const { t } = this.props;
const textKey = `userMedia.${this.props.browser}GrantPermissions`;
return (
<FilmstripOnlyOverlayFrame
icon = 'icon-mic-camera-combined'
isLightOverlay = { true }>
<div className = 'inlay-filmstrip-only__container'>
<div className = 'inlay-filmstrip-only__title'>
{
t('startupoverlay.title',
{ app: interfaceConfig.APP_NAME })
}
</div>
<div className = 'inlay-filmstrip-only__text'>
{
translateToHTML(t, textKey)
}
</div>
</div>
</FilmstripOnlyOverlayFrame>
);
}
}
export default translate(
connect(abstractMapStateToProps)(UserMediaPermissionsFilmstripOnlyOverlay));

View File

@ -1,19 +1,7 @@
// @flow // @flow
export { default as FilmstripOnlyOverlayFrame } from './FilmstripOnlyOverlayFrame';
export { default as OverlayFrame } from './OverlayFrame'; export { default as OverlayFrame } from './OverlayFrame';
export {
default as PageReloadFilmstripOnlyOverlay
} from './PageReloadFilmstripOnlyOverlay';
export { default as PageReloadOverlay } from './PageReloadOverlay'; export { default as PageReloadOverlay } from './PageReloadOverlay';
export {
default as SuspendedFilmstripOnlyOverlay
} from './SuspendedFilmstripOnlyOverlay';
export { default as SuspendedOverlay } from './SuspendedOverlay'; export { default as SuspendedOverlay } from './SuspendedOverlay';
export { export { default as UserMediaPermissionsOverlay } from './UserMediaPermissionsOverlay';
default as UserMediaPermissionsFilmstripOnlyOverlay
} from './UserMediaPermissionsFilmstripOnlyOverlay';
export {
default as UserMediaPermissionsOverlay
} from './UserMediaPermissionsOverlay';

View File

@ -1,11 +1,8 @@
// @flow // @flow
import { import {
PageReloadFilmstripOnlyOverlay,
PageReloadOverlay, PageReloadOverlay,
SuspendedFilmstripOnlyOverlay,
SuspendedOverlay, SuspendedOverlay,
UserMediaPermissionsFilmstripOnlyOverlay,
UserMediaPermissionsOverlay UserMediaPermissionsOverlay
} from './components/web'; } from './components/web';
@ -17,22 +14,9 @@ declare var interfaceConfig: Object;
* @returns {Array<Object>} * @returns {Array<Object>}
*/ */
export function getOverlays(): Array<Object> { export function getOverlays(): Array<Object> {
const overlays = [ return [
PageReloadOverlay,
SuspendedOverlay, SuspendedOverlay,
UserMediaPermissionsOverlay UserMediaPermissionsOverlay
]; ];
const filmstripOnly
= typeof interfaceConfig === 'object' && interfaceConfig.filmStripOnly;
if (filmstripOnly) {
overlays.push(
PageReloadFilmstripOnlyOverlay,
SuspendedFilmstripOnlyOverlay,
UserMediaPermissionsFilmstripOnlyOverlay);
} else {
overlays.push(PageReloadOverlay);
}
return overlays;
} }

View File

@ -5,22 +5,14 @@ import { translate } from '../../../base/i18n';
import { IconSettings } from '../../../base/icons'; import { IconSettings } from '../../../base/icons';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components'; import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
import { openDeviceSelectionPopup } from '../../../device-selection';
import { openSettingsDialog } from '../../actions'; import { openSettingsDialog } from '../../actions';
import { SETTINGS_TABS } from '../../constants'; import { SETTINGS_TABS } from '../../constants';
declare var interfaceConfig: Object;
/** /**
* The type of the React {@code Component} props of {@link SettingsButton}. * The type of the React {@code Component} props of {@link SettingsButton}.
*/ */
type Props = AbstractButtonProps & { type Props = AbstractButtonProps & {
/**
* Whether we are in filmstrip only mode or not.
*/
_filmstripOnly: boolean,
/** /**
* The default tab at which the settings dialog will be opened. * The default tab at which the settings dialog will be opened.
*/ */
@ -49,36 +41,12 @@ class SettingsButton extends AbstractButton<Props, *> {
*/ */
_handleClick() { _handleClick() {
const { const {
_filmstripOnly,
defaultTab = SETTINGS_TABS.DEVICES, defaultTab = SETTINGS_TABS.DEVICES,
dispatch } = this.props; dispatch } = this.props;
sendAnalytics(createToolbarEvent('settings')); sendAnalytics(createToolbarEvent('settings'));
if (_filmstripOnly) { dispatch(openSettingsDialog(defaultTab));
dispatch(openDeviceSelectionPopup());
} else {
dispatch(openSettingsDialog(defaultTab));
}
} }
} }
/** export default translate(connect()(SettingsButton));
* Maps (parts of) the redux state to the associated props for the
* {@code SettingsButton} component.
*
* @param {Object} state - The Redux state.
* @private
* @returns {{
* _filmstripOnly: boolean
* }}
*/
function _mapStateToProps(state): Object { // eslint-disable-line no-unused-vars
// XXX: We are not currently using state here, but in the future, when
// interfaceConfig is part of redux we will.
return {
_filmstripOnly: Boolean(interfaceConfig.filmStripOnly)
};
}
export default translate(connect(_mapStateToProps)(SettingsButton));

View File

@ -25,10 +25,6 @@ export * from './actions.native';
*/ */
export function dockToolbox(dock: boolean): Function { export function dockToolbox(dock: boolean): Function {
return (dispatch: Dispatch<any>, getState: Function) => { return (dispatch: Dispatch<any>, getState: Function) => {
if (interfaceConfig.filmStripOnly) {
return;
}
const { timeoutMS, visible } = getState()['features/toolbox']; const { timeoutMS, visible } = getState()['features/toolbox'];
if (dock) { if (dock) {

View File

@ -99,9 +99,6 @@ export function shouldDisplayTileView(state: Object = {}) {
// Editing etherpad // Editing etherpad
state['features/etherpad']?.editing state['features/etherpad']?.editing
// We're in filmstrip-only mode
|| (typeof interfaceConfig === 'object' && interfaceConfig?.filmStripOnly)
// We pinned a participant // We pinned a participant
|| getPinnedParticipant(state) || getPinnedParticipant(state)