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:
parent
f6127d45e9
commit
12c835dd91
|
@ -28,9 +28,6 @@ body {
|
|||
overflow: hidden;
|
||||
color: $defaultColor;
|
||||
background: $defaultBackground;
|
||||
&.filmstrip-only {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,16 +67,6 @@ body {
|
|||
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 {
|
||||
margin: 0;
|
||||
}
|
||||
|
|
|
@ -27,84 +27,4 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
transition: opacity 1s;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
* flex-direction: column-reverse. The remove videos in filmstrip should
|
||||
|
|
|
@ -8,16 +8,10 @@
|
|||
position: fixed;
|
||||
z-index: $overlayZ;
|
||||
background: $defaultBackground;
|
||||
&.filmstrip-only {
|
||||
@include transparentBg($filmstripOnlyOverlayBg, 0.8);
|
||||
}
|
||||
}
|
||||
|
||||
&__container-light {
|
||||
@include transparentBg($defaultBackground, 0.7);
|
||||
&.filmstrip-only {
|
||||
@include transparentBg($filmstripOnlyOverlayBg, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
&__content {
|
||||
|
@ -27,11 +21,6 @@
|
|||
width: 56%;
|
||||
left: 50%;
|
||||
@include transform(translateX(-50%));
|
||||
&.filmstrip-only {
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
@include transform(none);
|
||||
}
|
||||
|
||||
&_bottom {
|
||||
position: absolute;
|
||||
|
|
|
@ -41,7 +41,6 @@ $overlayButtonBg: #0074E0;
|
|||
* Color variables
|
||||
**/
|
||||
$defaultBackground: #474747;
|
||||
$filmstripOnlyOverlayBg: #000;
|
||||
$reloadProgressBarBg: #0074E0;
|
||||
|
||||
/**
|
||||
|
@ -59,10 +58,6 @@ $dialogErrorText: #344563;
|
|||
**/
|
||||
$inlayColorBg: lighten($defaultBackground, 20%);
|
||||
$inlayBorderColor: lighten($baseLight, 10%);
|
||||
$inlayIconBg: #000;
|
||||
$inlayIconColor: #fff;
|
||||
$inlayFilmstripOnlyColor: #474747;
|
||||
$inlayFilmstripOnlyBg: #fff;
|
||||
|
||||
// Main controls
|
||||
$placeHolderColor: #a7a7a7;
|
||||
|
|
|
@ -13,9 +13,7 @@
|
|||
height: 180,
|
||||
parentNode: undefined,
|
||||
configOverwrite: {},
|
||||
interfaceConfigOverwrite: {
|
||||
filmStripOnly: true
|
||||
}
|
||||
interfaceConfigOverwrite: {}
|
||||
}
|
||||
var api = new JitsiMeetExternalAPI(domain, options);
|
||||
</script>
|
||||
|
|
|
@ -97,11 +97,6 @@ var interfaceConfig = {
|
|||
|
||||
FILM_STRIP_MAX_HEIGHT: 120,
|
||||
|
||||
/**
|
||||
* Whether to only show the filmstrip (and hide the toolbar).
|
||||
*/
|
||||
filmStripOnly: false,
|
||||
|
||||
GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true,
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global APP, $, config, interfaceConfig */
|
||||
/* global APP, $, config */
|
||||
|
||||
|
||||
const UI = {};
|
||||
|
@ -143,9 +143,7 @@ UI.start = function() {
|
|||
$.prompt.setDefaults({ persistent: false });
|
||||
|
||||
VideoLayout.init(eventEmitter);
|
||||
if (!interfaceConfig.filmStripOnly) {
|
||||
VideoLayout.initLargeVideo();
|
||||
}
|
||||
VideoLayout.initLargeVideo();
|
||||
|
||||
// Do not animate the video area on UI start (second argument passed into
|
||||
// resizeVideoArea) because the animation is not visible anyway. Plus with
|
||||
|
@ -161,10 +159,7 @@ UI.start = function() {
|
|||
$('body').addClass('desktop-browser');
|
||||
}
|
||||
|
||||
if (interfaceConfig.filmStripOnly) {
|
||||
$('body').addClass('filmstrip-only');
|
||||
APP.store.dispatch(setNotificationsEnabled(false));
|
||||
} else if (config.iAmRecorder) {
|
||||
if (config.iAmRecorder) {
|
||||
// in case of iAmSipGateway keep local video visible
|
||||
if (!config.iAmSipGateway) {
|
||||
VideoLayout.setLocalVideoVisible(false);
|
||||
|
|
|
@ -135,10 +135,6 @@ export default class RemoteVideo extends SmallVideo {
|
|||
* @private
|
||||
*/
|
||||
_generatePopupContent() {
|
||||
if (interfaceConfig.filmStripOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
const remoteVideoMenuContainer
|
||||
= this.container.querySelector('.remotevideomenu');
|
||||
|
||||
|
|
|
@ -699,7 +699,7 @@ export default class SmallVideo {
|
|||
alwaysVisible = { showConnectionIndicator }
|
||||
iconSize = { iconSize }
|
||||
isLocalVideo = { this.isLocal }
|
||||
enableStatsDisplay = { !interfaceConfig.filmStripOnly }
|
||||
enableStatsDisplay = { true }
|
||||
participantId = { this.id }
|
||||
statsPopoverPosition = { statsPopoverPosition } />
|
||||
: null }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global APP, $, interfaceConfig */
|
||||
/* global APP, $ */
|
||||
|
||||
import Logger from 'jitsi-meet-logger';
|
||||
|
||||
|
@ -264,10 +264,6 @@ const VideoLayout = {
|
|||
* @returns {void}
|
||||
*/
|
||||
onPinChange(pinnedParticipantID) {
|
||||
if (interfaceConfig.filmStripOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
getAllThumbnails().forEach(thumbnail =>
|
||||
thumbnail.focus(pinnedParticipantID === thumbnail.getId()));
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global APP, $, interfaceConfig */
|
||||
/* global APP, $ */
|
||||
|
||||
import Logger from 'jitsi-meet-logger';
|
||||
|
||||
|
@ -203,14 +203,12 @@ const KeyboardShortcut = {
|
|||
});
|
||||
this._addShortcutToHelp('SPACE', 'keyboardShortcuts.pushToTalk');
|
||||
|
||||
if (!interfaceConfig.filmStripOnly) {
|
||||
this.registerShortcut('T', null, () => {
|
||||
sendAnalytics(createShortcutEvent('speaker.stats'));
|
||||
APP.store.dispatch(toggleDialog(SpeakerStats, {
|
||||
conference: APP.conference
|
||||
}));
|
||||
}, 'keyboardShortcuts.showSpeakerStats');
|
||||
}
|
||||
this.registerShortcut('T', null, () => {
|
||||
sendAnalytics(createShortcutEvent('speaker.stats'));
|
||||
APP.store.dispatch(toggleDialog(SpeakerStats, {
|
||||
conference: APP.conference
|
||||
}));
|
||||
}, 'keyboardShortcuts.showSpeakerStats');
|
||||
|
||||
/**
|
||||
* FIXME: Currently focus keys are directly implemented below in
|
||||
|
|
|
@ -54,6 +54,5 @@ export default [
|
|||
'UNSUPPORTED_BROWSERS',
|
||||
'VERTICAL_FILMSTRIP',
|
||||
'VIDEO_LAYOUT_FIT',
|
||||
'VIDEO_QUALITY_LABEL_DISABLED',
|
||||
'filmStripOnly'
|
||||
'VIDEO_QUALITY_LABEL_DISABLED'
|
||||
];
|
||||
|
|
|
@ -84,13 +84,7 @@ class Watermarks extends Component<Props, State> {
|
|||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
let showBrandWatermark;
|
||||
|
||||
if (interfaceConfig.filmStripOnly) {
|
||||
showBrandWatermark = false;
|
||||
} else {
|
||||
showBrandWatermark = interfaceConfig.SHOW_BRAND_WATERMARK;
|
||||
}
|
||||
const showBrandWatermark = interfaceConfig.SHOW_BRAND_WATERMARK;
|
||||
|
||||
this.state = {
|
||||
brandWatermarkLink:
|
||||
|
@ -237,12 +231,11 @@ function _mapStateToProps(state, ownProps) {
|
|||
const {
|
||||
DEFAULT_LOGO_URL,
|
||||
JITSI_WATERMARK_LINK,
|
||||
SHOW_JITSI_WATERMARK,
|
||||
filmStripOnly
|
||||
SHOW_JITSI_WATERMARK
|
||||
} = interfaceConfig;
|
||||
let _showJitsiWatermark = (!filmStripOnly
|
||||
&& (customizationReady && !customizationFailed)
|
||||
&& SHOW_JITSI_WATERMARK)
|
||||
let _showJitsiWatermark = (
|
||||
customizationReady && !customizationFailed
|
||||
&& SHOW_JITSI_WATERMARK)
|
||||
|| !isValidRoom;
|
||||
let _logoUrl = logoImageUrl;
|
||||
let _logoLink = logoClickUrl;
|
||||
|
|
|
@ -152,11 +152,9 @@ StateListenerRegistry.register(
|
|||
* @returns {void}
|
||||
*/
|
||||
function _addChatMsgListener(conference, store) {
|
||||
if ((typeof interfaceConfig === 'object' && interfaceConfig.filmStripOnly)
|
||||
|| (typeof APP !== 'undefined' && !isButtonEnabled('chat'))
|
||||
if ((typeof APP !== 'undefined' && !isButtonEnabled('chat'))
|
||||
|| store.getState()['features/base/config'].iAmRecorder) {
|
||||
// We don't register anything on web if we're in filmStripOnly mode, or
|
||||
// the chat button is not enabled in interfaceConfig.
|
||||
// We don't register anything on web if the chat button is not enabled in interfaceConfig
|
||||
// or we are in iAmRecorder mode
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import { CalleeInfoContainer } from '../../../invite';
|
|||
import { LargeVideo } from '../../../large-video';
|
||||
import { KnockingParticipantList, LobbyScreen } from '../../../lobby';
|
||||
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 { LAYOUTS, getCurrentLayout } from '../../../video-layout';
|
||||
import { maybeShowSuboptimalExperienceNotification } from '../../functions';
|
||||
|
@ -28,7 +28,6 @@ import Labels from './Labels';
|
|||
import { default as Notice } from './Notice';
|
||||
|
||||
declare var APP: Object;
|
||||
declare var config: Object;
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
|
@ -175,18 +174,13 @@ class Conference extends AbstractConference<Props, *> {
|
|||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const {
|
||||
// XXX The character casing of the name filmStripOnly utilized by
|
||||
// interfaceConfig is obsolete but legacy support is required.
|
||||
filmStripOnly: filmstripOnly
|
||||
} = interfaceConfig;
|
||||
const {
|
||||
_iAmRecorder,
|
||||
_isLobbyScreenVisible,
|
||||
_layoutClassName,
|
||||
_showPrejoin
|
||||
} = this.props;
|
||||
const hideLabels = filmstripOnly || _iAmRecorder;
|
||||
const hideLabels = _iAmRecorder;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -198,18 +192,18 @@ class Conference extends AbstractConference<Props, *> {
|
|||
<div id = 'videospace'>
|
||||
<LargeVideo />
|
||||
<KnockingParticipantList />
|
||||
<Filmstrip filmstripOnly = { filmstripOnly } />
|
||||
<Filmstrip />
|
||||
{ hideLabels || <Labels /> }
|
||||
</div>
|
||||
|
||||
{ filmstripOnly || _showPrejoin || _isLobbyScreenVisible || <Toolbox /> }
|
||||
{ filmstripOnly || <Chat /> }
|
||||
{ _showPrejoin || _isLobbyScreenVisible || <Toolbox /> }
|
||||
<Chat />
|
||||
|
||||
{ this.renderNotificationsContainer() }
|
||||
|
||||
<CalleeInfoContainer />
|
||||
|
||||
{ !filmstripOnly && _showPrejoin && <Prejoin />}
|
||||
{ _showPrejoin && <Prejoin />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -256,9 +250,6 @@ class Conference extends AbstractConference<Props, *> {
|
|||
dispatch(connect());
|
||||
|
||||
maybeShowSuboptimalExperienceNotification(dispatch, t);
|
||||
|
||||
interfaceConfig.filmStripOnly
|
||||
&& dispatch(setToolboxAlwaysVisible(true));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ export function maybeOpenFeedbackDialog(conference: Object) {
|
|||
const state = getState();
|
||||
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
|
||||
// from being taken with regards to showing feedback.
|
||||
} else if (state['features/base/dialog'].component === FeedbackDialog) {
|
||||
|
|
|
@ -17,8 +17,6 @@ import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
|
|||
import { setFilmstripHovered, setFilmstripVisible } from '../../actions';
|
||||
import { shouldRemoteVideosBeVisible } from '../../functions';
|
||||
|
||||
import Toolbar from './Toolbar';
|
||||
|
||||
declare var APP: Object;
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
|
@ -42,11 +40,6 @@ type Props = {
|
|||
*/
|
||||
_columns: number,
|
||||
|
||||
/**
|
||||
* Whether the UI/UX is filmstrip-only.
|
||||
*/
|
||||
_filmstripOnly: boolean,
|
||||
|
||||
/**
|
||||
* The width of the filmstrip.
|
||||
*/
|
||||
|
@ -142,14 +135,12 @@ class Filmstrip extends Component <Props> {
|
|||
* @inheritdoc
|
||||
*/
|
||||
componentDidMount() {
|
||||
if (!this.props._filmstripOnly) {
|
||||
APP.keyboardshortcut.registerShortcut(
|
||||
'F',
|
||||
'filmstripPopover',
|
||||
this._onShortcutToggleFilmstrip,
|
||||
'keyboardShortcuts.toggleFilmstrip'
|
||||
);
|
||||
}
|
||||
APP.keyboardshortcut.registerShortcut(
|
||||
'F',
|
||||
'filmstripPopover',
|
||||
this._onShortcutToggleFilmstrip,
|
||||
'keyboardShortcuts.toggleFilmstrip'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -207,7 +198,7 @@ class Filmstrip extends Component <Props> {
|
|||
let toolbar = null;
|
||||
|
||||
if (!this.props._hideToolbar) {
|
||||
toolbar = this.props._filmstripOnly ? <Toolbar /> : this._renderToggleButton();
|
||||
toolbar = this._renderToggleButton();
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -367,24 +358,20 @@ class Filmstrip extends Component <Props> {
|
|||
function _mapStateToProps(state) {
|
||||
const { iAmSipGateway } = state['features/base/config'];
|
||||
const { hovered, visible } = state['features/filmstrip'];
|
||||
const isFilmstripOnly = Boolean(interfaceConfig.filmStripOnly);
|
||||
const reduceHeight
|
||||
= !isFilmstripOnly && state['features/toolbox'].visible && interfaceConfig.TOOLBAR_BUTTONS.length;
|
||||
= state['features/toolbox'].visible && interfaceConfig.TOOLBAR_BUTTONS.length;
|
||||
const remoteVideosVisible = shouldRemoteVideosBeVisible(state);
|
||||
const { isOpen: shiftRight } = state['features/chat'];
|
||||
const className = `${remoteVideosVisible ? '' : 'hide-videos'} ${
|
||||
reduceHeight ? 'reduce-height' : ''
|
||||
} ${shiftRight ? 'shift-right' : ''}`.trim();
|
||||
const videosClassName = `filmstrip__videos${
|
||||
isFilmstripOnly ? ' filmstrip__videos-filmstripOnly' : ''}${
|
||||
visible ? '' : ' hidden'}`;
|
||||
const videosClassName = `filmstrip__videos${visible ? '' : ' hidden'}`;
|
||||
const { gridDimensions = {}, filmstripWidth } = state['features/filmstrip'].tileViewDimensions;
|
||||
|
||||
return {
|
||||
_className: className,
|
||||
_columns: gridDimensions.columns,
|
||||
_currentLayout: getCurrentLayout(state),
|
||||
_filmstripOnly: isFilmstripOnly,
|
||||
_filmstripWidth: filmstripWidth,
|
||||
_hideScrollbar: Boolean(iAmSipGateway),
|
||||
_hideToolbar: Boolean(iAmSipGateway),
|
||||
|
|
|
@ -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);
|
|
@ -56,9 +56,6 @@ export function shouldRemoteVideosBeVisible(state: Object) {
|
|||
|| ((pinnedParticipant = getPinnedParticipant(state))
|
||||
&& pinnedParticipant.local)))
|
||||
|
||||
|| (typeof interfaceConfig === 'object'
|
||||
&& interfaceConfig.filmStripOnly)
|
||||
|
||||
|| state['features/base/config'].disable1On1Mode);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
|
@ -21,44 +21,10 @@ type Props = {
|
|||
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.
|
||||
*/
|
||||
export default class OverlayFrame extends Component<Props, State> {
|
||||
/**
|
||||
* 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
|
||||
};
|
||||
}
|
||||
|
||||
export default class OverlayFrame extends Component<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
@ -66,20 +32,11 @@ export default class OverlayFrame extends Component<Props, State> {
|
|||
* @returns {ReactElement|null}
|
||||
*/
|
||||
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 (
|
||||
<div
|
||||
className = { containerClass }
|
||||
className = { this.props.isLightOverlay ? 'overlay__container-light' : 'overlay__container' }
|
||||
id = 'overlay'>
|
||||
<div className = { contentClass }>
|
||||
<div className = { 'overlay__content' }>
|
||||
{
|
||||
this.props.children
|
||||
}
|
||||
|
|
|
@ -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));
|
|
@ -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);
|
|
@ -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));
|
|
@ -1,19 +1,7 @@
|
|||
// @flow
|
||||
|
||||
export { default as FilmstripOnlyOverlayFrame } from './FilmstripOnlyOverlayFrame';
|
||||
export { default as OverlayFrame } from './OverlayFrame';
|
||||
|
||||
export {
|
||||
default as PageReloadFilmstripOnlyOverlay
|
||||
} from './PageReloadFilmstripOnlyOverlay';
|
||||
export { default as PageReloadOverlay } from './PageReloadOverlay';
|
||||
export {
|
||||
default as SuspendedFilmstripOnlyOverlay
|
||||
} from './SuspendedFilmstripOnlyOverlay';
|
||||
export { default as SuspendedOverlay } from './SuspendedOverlay';
|
||||
export {
|
||||
default as UserMediaPermissionsFilmstripOnlyOverlay
|
||||
} from './UserMediaPermissionsFilmstripOnlyOverlay';
|
||||
export {
|
||||
default as UserMediaPermissionsOverlay
|
||||
} from './UserMediaPermissionsOverlay';
|
||||
export { default as UserMediaPermissionsOverlay } from './UserMediaPermissionsOverlay';
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
// @flow
|
||||
|
||||
import {
|
||||
PageReloadFilmstripOnlyOverlay,
|
||||
PageReloadOverlay,
|
||||
SuspendedFilmstripOnlyOverlay,
|
||||
SuspendedOverlay,
|
||||
UserMediaPermissionsFilmstripOnlyOverlay,
|
||||
UserMediaPermissionsOverlay
|
||||
} from './components/web';
|
||||
|
||||
|
@ -17,22 +14,9 @@ declare var interfaceConfig: Object;
|
|||
* @returns {Array<Object>}
|
||||
*/
|
||||
export function getOverlays(): Array<Object> {
|
||||
const overlays = [
|
||||
return [
|
||||
PageReloadOverlay,
|
||||
SuspendedOverlay,
|
||||
UserMediaPermissionsOverlay
|
||||
];
|
||||
|
||||
const filmstripOnly
|
||||
= typeof interfaceConfig === 'object' && interfaceConfig.filmStripOnly;
|
||||
|
||||
if (filmstripOnly) {
|
||||
overlays.push(
|
||||
PageReloadFilmstripOnlyOverlay,
|
||||
SuspendedFilmstripOnlyOverlay,
|
||||
UserMediaPermissionsFilmstripOnlyOverlay);
|
||||
} else {
|
||||
overlays.push(PageReloadOverlay);
|
||||
}
|
||||
|
||||
return overlays;
|
||||
}
|
||||
|
|
|
@ -5,22 +5,14 @@ import { translate } from '../../../base/i18n';
|
|||
import { IconSettings } from '../../../base/icons';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
|
||||
import { openDeviceSelectionPopup } from '../../../device-selection';
|
||||
import { openSettingsDialog } from '../../actions';
|
||||
import { SETTINGS_TABS } from '../../constants';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link SettingsButton}.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -49,36 +41,12 @@ class SettingsButton extends AbstractButton<Props, *> {
|
|||
*/
|
||||
_handleClick() {
|
||||
const {
|
||||
_filmstripOnly,
|
||||
defaultTab = SETTINGS_TABS.DEVICES,
|
||||
dispatch } = this.props;
|
||||
|
||||
sendAnalytics(createToolbarEvent('settings'));
|
||||
if (_filmstripOnly) {
|
||||
dispatch(openDeviceSelectionPopup());
|
||||
} else {
|
||||
dispatch(openSettingsDialog(defaultTab));
|
||||
}
|
||||
dispatch(openSettingsDialog(defaultTab));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
export default translate(connect()(SettingsButton));
|
||||
|
|
|
@ -25,10 +25,6 @@ export * from './actions.native';
|
|||
*/
|
||||
export function dockToolbox(dock: boolean): Function {
|
||||
return (dispatch: Dispatch<any>, getState: Function) => {
|
||||
if (interfaceConfig.filmStripOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { timeoutMS, visible } = getState()['features/toolbox'];
|
||||
|
||||
if (dock) {
|
||||
|
|
|
@ -99,9 +99,6 @@ export function shouldDisplayTileView(state: Object = {}) {
|
|||
// Editing etherpad
|
||||
state['features/etherpad']?.editing
|
||||
|
||||
// We're in filmstrip-only mode
|
||||
|| (typeof interfaceConfig === 'object' && interfaceConfig?.filmStripOnly)
|
||||
|
||||
// We pinned a participant
|
||||
|| getPinnedParticipant(state)
|
||||
|
||||
|
|
Loading…
Reference in New Issue