Self view refactor (#10620)

* feat: Drops hide self-view setting from profile tab.

* feat: Moves function for disableSelfView value in base/settings.

* squash: Drops notification.

* feat: Move hide self view option in more tab.

* feat: Move hide self view option in more tab.

* feat: Adds option to disable self view UI settings.

* squash: Disable settings when controlled from config.
This commit is contained in:
Дамян Минков 2021-12-16 10:55:45 -06:00 committed by GitHub
parent 2a236b9327
commit 5dee37dd82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 152 additions and 142 deletions

View File

@ -89,6 +89,9 @@ var config = {
// Disables self-view tile. (hides it from tile view and from filmstrip)
// disableSelfView: false,
// Disables self-view settings in UI
// disableSelfViewSettings: false,
// Disables ICE/UDP by filtering out local and remote UDP candidates in
// signalling.
// webrtcIceUdpDisable: false,

View File

@ -857,6 +857,7 @@
"selectAudioOutput": "Audio output",
"selectCamera": "Camera",
"selectMic": "Microphone",
"selfView": "Self view",
"sounds": "Sounds",
"speakers": "Speakers",
"startAudioMuted": "Everyone starts muted",

View File

@ -17,6 +17,7 @@ import '../prejoin/middleware';
import '../remote-control/middleware';
import '../screen-share/middleware';
import '../shared-video/middleware';
import '../settings/middleware';
import '../talk-while-muted/middleware';
import '../virtual-background/middleware';
import '../facial-recognition/middleware';

View File

@ -115,6 +115,7 @@ export default [
'disableResponsiveTiles',
'disableRtx',
'disableSelfView',
'disableSelfViewSettings',
'disableScreensharingVirtualBackground',
'disableShortcuts',
'disableShowMoreStats',

View File

@ -125,12 +125,6 @@ function _setConfig({ dispatch, getState }, next, action) {
}));
}
if (action.config.disableSelfView) {
dispatch(updateSettings({
disableSelfView: true
}));
}
dispatch(updateConfig(config));
// FIXME On Web we rely on the global 'config' variable which gets altered

View File

@ -1,5 +1,6 @@
// @flow
import { CONFIG_WHITELIST } from '../config';
import { getParticipantCount } from '../participants';
import { toState } from '../redux';
import { parseURLParams } from '../util';
@ -256,3 +257,23 @@ export function shouldHideShareAudioHelper(state: Object): boolean {
return state['features/base/settings'].hideShareAudioHelper;
}
/**
* Whether we should hide self view.
*
* @param {Object} state - Redux state.
* @returns {boolean}
*/
export function shouldHideSelfView(state: Object) {
return getParticipantCount(state) === 1 ? false : getHideSelfView(state);
}
/**
* Gets the disable self view setting.
*
* @param {Object} state - Redux state.
* @returns {boolean}
*/
export function getHideSelfView(state: Object) {
return state['features/base/config'].disableSelfView || state['features/base/settings'].disableSelfView;
}

View File

@ -2,6 +2,7 @@
import type { Dispatch } from 'redux';
import { getLocalParticipant, getParticipantById, pinParticipant } from '../base/participants';
import { shouldHideSelfView } from '../base/settings/functions.any';
import {
SET_HORIZONTAL_VIEW_DIMENSIONS,
@ -23,7 +24,6 @@ import {
calculateThumbnailSizeForTileView,
calculateThumbnailSizeForVerticalView
} from './functions';
import { getDisableSelfView } from './functions.any';
export * from './actions.any';
@ -79,7 +79,7 @@ export function setVerticalViewDimensions() {
return (dispatch: Dispatch<any>, getState: Function) => {
const state = getState();
const { clientHeight = 0, clientWidth = 0 } = state['features/base/responsive-ui'];
const disableSelfView = getDisableSelfView(state);
const disableSelfView = shouldHideSelfView(state);
const thumbnails = calculateThumbnailSizeForVerticalView(clientWidth);
dispatch({
@ -107,7 +107,7 @@ export function setHorizontalViewDimensions() {
return (dispatch: Dispatch<any>, getState: Function) => {
const state = getState();
const { clientHeight = 0, clientWidth = 0 } = state['features/base/responsive-ui'];
const disableSelfView = getDisableSelfView(state);
const disableSelfView = shouldHideSelfView(state);
const thumbnails = calculateThumbnailSizeForHorizontalView(clientHeight);
dispatch({

View File

@ -7,9 +7,9 @@ import { getLocalParticipant } from '../../../base/participants';
import { Platform } from '../../../base/react';
import { connect } from '../../../base/redux';
import { ASPECT_RATIO_NARROW } from '../../../base/responsive-ui/constants';
import { shouldHideSelfView } from '../../../base/settings/functions.any';
import { setVisibleRemoteParticipants } from '../../actions';
import { isFilmstripVisible, shouldRemoteVideosBeVisible } from '../../functions';
import { getDisableSelfView } from '../../functions.any';
import LocalThumbnail from './LocalThumbnail';
import Thumbnail from './Thumbnail';
@ -283,7 +283,7 @@ class Filmstrip extends PureComponent<Props> {
*/
function _mapStateToProps(state) {
const { enabled, remoteParticipants } = state['features/filmstrip'];
const disableSelfView = getDisableSelfView(state);
const disableSelfView = shouldHideSelfView(state);
const showRemoteVideos = shouldRemoteVideosBeVisible(state);
const responsiveUI = state['features/base/responsive-ui'];

View File

@ -10,8 +10,8 @@ import type { Dispatch } from 'redux';
import { getLocalParticipant, getParticipantCountWithFake } from '../../../base/participants';
import { connect } from '../../../base/redux';
import { shouldHideSelfView } from '../../../base/settings/functions.any';
import { setVisibleRemoteParticipants } from '../../actions.web';
import { getDisableSelfView } from '../../functions.any';
import Thumbnail from './Thumbnail';
import styles from './styles';
@ -275,7 +275,7 @@ class TileView extends PureComponent<Props> {
function _mapStateToProps(state) {
const responsiveUi = state['features/base/responsive-ui'];
const { remoteParticipants, tileViewDimensions } = state['features/filmstrip'];
const disableSelfView = getDisableSelfView(state);
const disableSelfView = shouldHideSelfView(state);
const { height } = tileViewDimensions.thumbnailSize;
const { columns } = tileViewDimensions;

View File

@ -14,6 +14,7 @@ import { isMobileBrowser } from '../../../base/environment/utils';
import { translate } from '../../../base/i18n';
import { Icon, IconMenuDown, IconMenuUp } from '../../../base/icons';
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, getCurrentLayout } from '../../../video-layout';
@ -26,7 +27,6 @@ import {
TOOLBAR_HEIGHT_MOBILE
} from '../../constants';
import { shouldRemoteVideosBeVisible } from '../../functions';
import { getDisableSelfView } from '../../functions.any';
import AudioTracksContainer from './AudioTracksContainer';
import Thumbnail from './Thumbnail';
@ -580,7 +580,7 @@ function _mapStateToProps(state) {
thumbnailSize: tileViewThumbnailSize
} = state['features/filmstrip'].tileViewDimensions;
const _currentLayout = getCurrentLayout(state);
const disableSelfView = getDisableSelfView(state);
const disableSelfView = shouldHideSelfView(state);
const { clientHeight, clientWidth } = state['features/base/responsive-ui'];
const availableSpace = clientHeight - filmstripHeight;

View File

@ -3,8 +3,8 @@ import React, { Component } from 'react';
import { shouldComponentUpdate } from 'react-window';
import { connect } from '../../../base/redux';
import { shouldHideSelfView } from '../../../base/settings/functions.any';
import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
import { getDisableSelfView } from '../../functions.any';
import Thumbnail from './Thumbnail';
@ -118,7 +118,7 @@ function _mapStateToProps(state, ownProps) {
const { remote, local } = state['features/base/participants'];
const remoteParticipantsLength = remoteParticipants.length;
const { testing = {} } = state['features/base/config'];
const disableSelfView = getDisableSelfView(state);
const disableSelfView = shouldHideSelfView(state);
const enableThumbnailReordering = testing.enableThumbnailReordering ?? true;
if (_currentLayout === LAYOUTS.TILE_VIEW) {

View File

@ -1,7 +1,5 @@
// @flow
import { getParticipantCount } from '../base/participants';
import { setRemoteParticipants } from './actions';
/**
@ -82,16 +80,3 @@ export function updateRemoteParticipantsOnLeave(store: Object, participantId: ?s
reorderedParticipants.delete(participantId)
&& store.dispatch(setRemoteParticipants(Array.from(reorderedParticipants)));
}
/**
* Gets the disable self view flag.
*
* @param {Object} state - Redux state.
* @returns {boolean}
*/
export function getDisableSelfView(state: Object) {
const { disableSelfView } = state['features/base/settings'];
const participantsCount = getParticipantCount(state);
return participantsCount === 1 ? false : disableSelfView;
}

View File

@ -4,6 +4,7 @@ import { isMobileBrowser } from '../base/environment/utils';
import { getParticipantCountWithFake } from '../base/participants';
import { StateListenerRegistry, equals } from '../base/redux';
import { clientResized } from '../base/responsive-ui';
import { shouldHideSelfView } from '../base/settings';
import { setFilmstripVisible } from '../filmstrip/actions';
import { getParticipantsPaneOpen } from '../participants-pane/functions';
import { setOverflowDrawer } from '../toolbox/actions.web';
@ -30,7 +31,7 @@ StateListenerRegistry.register(
/* selector */ state => {
return {
numberOfParticipants: getParticipantCountWithFake(state),
disableSelfView: state['features/base/settings'].disableSelfView
disableSelfView: shouldHideSelfView(state)
};
},
/* listener */ (currentState, store) => {

View File

@ -1 +0,0 @@
import './middleware.any';

View File

@ -1,40 +0,0 @@
/* @flow */
import { CONFERENCE_JOINED } from '../base/conference';
import { MiddlewareRegistry } from '../base/redux';
import { openSettingsDialog, SETTINGS_TABS } from '../settings';
import {
showNotification
} from './actions';
import { NOTIFICATION_TIMEOUT_TYPE } from './constants';
import './middleware.any';
/**
* Middleware that captures actions to display notifications.
*
* @param {Store} store - The redux store.
* @returns {Function}
*/
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case CONFERENCE_JOINED: {
const { dispatch, getState } = store;
const { disableSelfView } = getState()['features/base/settings'];
if (disableSelfView) {
dispatch(showNotification({
titleKey: 'notify.selfViewTitle',
customActionNameKey: [ 'settings.title' ],
customActionHandler: [ () =>
dispatch(openSettingsDialog(SETTINGS_TABS.PROFILE))
]
}, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
}
break;
}
}
return next(action);
});

View File

@ -10,7 +10,6 @@ import {
import { openDialog } from '../base/dialog';
import { i18next } from '../base/i18n';
import { updateSettings } from '../base/settings';
import { NOTIFICATION_TIMEOUT_TYPE, showNotification } from '../notifications';
import { setPrejoinPageVisibility, setSkipPrejoinIsChanging } from '../prejoin/actions';
import { setScreenshareFramerate } from '../screen-share/actions';
@ -26,8 +25,6 @@ import {
getSoundsTabProps
} from './functions';
import { SETTINGS_TABS } from '.';
declare var APP: Object;
/**
@ -113,6 +110,10 @@ export function submitMoreTab(newState: Object): Function {
dispatch(setScreenshareFramerate(frameRate));
}
if (newState.hideSelfView !== currentState.hideSelfView) {
dispatch(updateSettings({ disableSelfView: newState.hideSelfView }));
}
};
}
@ -163,19 +164,6 @@ export function submitProfileTab(newState: Object): Function {
if (newState.email !== currentState.email) {
APP.conference.changeLocalEmail(newState.email);
}
if (newState.disableSelfView !== currentState.disableSelfView) {
dispatch(updateSettings({ disableSelfView: newState.disableSelfView }));
if (newState.disableSelfView) {
dispatch(showNotification({
titleKey: 'notify.selfViewTitle',
customActionNameKey: [ 'settings.title' ],
customActionHandler: [ () =>
dispatch(openSettingsDialog(SETTINGS_TABS.PROFILE))
]
}, NOTIFICATION_TIMEOUT_TYPE.STICKY));
}
}
};
}

View File

@ -35,6 +35,11 @@ export type Props = {
*/
desktopShareFramerates: Array<number>,
/**
* Whether to show hide self view setting.
*/
disableHideSelfView: boolean,
/**
* Whether or not follow me is currently active (enabled by some other participant).
*/
@ -65,6 +70,11 @@ export type Props = {
*/
showPrejoinPage: boolean,
/**
* Whether or not to hide self-view screen.
*/
hideSelfView: boolean,
/**
* Invoked to obtain translated strings.
*/
@ -114,6 +124,7 @@ class MoreTab extends AbstractDialogTab<Props, State> {
this._onLanguageItemSelect = this._onLanguageItemSelect.bind(this);
this._onShowPrejoinPageChanged = this._onShowPrejoinPageChanged.bind(this);
this._onKeyboardShortcutEnableChanged = this._onKeyboardShortcutEnableChanged.bind(this);
this._onHideSelfViewChanged = this._onHideSelfViewChanged.bind(this);
}
/**
@ -222,6 +233,19 @@ class MoreTab extends AbstractDialogTab<Props, State> {
super._onChange({ keyboardShortcutEnable: checked });
}
_onHideSelfViewChanged: (Object) => void;
/**
* Callback invoked to select if hide self view should be enabled.
*
* @param {Object} e - The key event to handle.
*
* @returns {void}
*/
_onHideSelfViewChanged({ target: { checked } }) {
super._onChange({ hideSelfView: checked });
}
/**
* Returns the React Element for the desktop share frame rate dropdown.
*
@ -300,6 +324,31 @@ class MoreTab extends AbstractDialogTab<Props, State> {
);
}
/**
* Returns the React Element for self view setting.
*
* @private
* @returns {ReactElement}
*/
_renderSelfViewCheckbox() {
const { hideSelfView, t } = this.props;
return (
<div
className = 'settings-sub-pane-element'
key = 'selfview'>
<h2 className = 'mock-atlaskit-label'>
{ t('settings.selfView') }
</h2>
<Checkbox
isChecked = { hideSelfView }
label = { t('videothumbnail.hideSelfView') }
name = 'hide-self-view'
onChange = { this._onHideSelfViewChanged } />
</div>
);
}
/**
* Returns the menu item for changing displayed language.
*
@ -404,7 +453,7 @@ class MoreTab extends AbstractDialogTab<Props, State> {
* @returns {ReactElement}
*/
_renderSettingsLeft() {
const { showPrejoinSettings } = this.props;
const { disableHideSelfView, showPrejoinSettings } = this.props;
return (
<div
@ -412,6 +461,7 @@ class MoreTab extends AbstractDialogTab<Props, State> {
key = 'settings-sub-pane-left'>
{ showPrejoinSettings && this._renderPrejoinScreenSettings() }
{ this._renderKeyboardShortcutCheckbox() }
{ !disableHideSelfView && this._renderSelfViewCheckbox() }
</div>
);
}

View File

@ -1,7 +1,6 @@
// @flow
import Button from '@atlaskit/button/standard-button';
import Checkbox from '@atlaskit/checkbox';
import { FieldTextStateless } from '@atlaskit/field-text';
import React from 'react';
@ -33,11 +32,6 @@ export type Props = {
*/
authLogin: string,
/**
* Whether or not to hide the self view.
*/
disableSelfView: boolean,
/**
* The display name to display for the local participant.
*/
@ -88,7 +82,6 @@ class ProfileTab extends AbstractDialogTab<Props> {
this._onAuthToggle = this._onAuthToggle.bind(this);
this._onDisplayNameChange = this._onDisplayNameChange.bind(this);
this._onEmailChange = this._onEmailChange.bind(this);
this._onChange = this._onChange.bind(this);
}
_onDisplayNameChange: (Object) => void;
@ -117,19 +110,6 @@ class ProfileTab extends AbstractDialogTab<Props> {
super._onChange({ email: value });
}
_onChange: (Object) => void;
/**
* Changes the disable self view state.
*
* @param {Object} e - The key event to handle.
*
* @returns {void}
*/
_onChange({ target }) {
super._onChange({ disableSelfView: target.checked });
}
/**
* Implements React's {@link Component#render()}.
*
@ -140,7 +120,6 @@ class ProfileTab extends AbstractDialogTab<Props> {
const {
authEnabled,
displayName,
disableSelfView,
email,
hideEmailInSettings,
readOnlyName,
@ -175,12 +154,6 @@ class ProfileTab extends AbstractDialogTab<Props> {
value = { email } />
</div>}
</div>
<br />
<Checkbox
isChecked = { disableSelfView }
label = { t('videothumbnail.hideSelfView') }
name = 'disableSelfView'
onChange = { this._onChange } />
{ authEnabled && this._renderAuth() }
</div>
);

View File

@ -244,6 +244,7 @@ function _mapStateToProps(state) {
...newProps,
currentFramerate: tabState.currentFramerate,
currentLanguage: tabState.currentLanguage,
hideSelfView: tabState.hideSelfView,
showPrejoinPage: tabState.showPrejoinPage
};
},

View File

@ -9,6 +9,7 @@ import {
isLocalParticipantModerator
} from '../base/participants';
import { toState } from '../base/redux';
import { getHideSelfView } from '../base/settings';
import { parseStandardURIString } from '../base/util';
import { isFollowMeActive } from '../follow-me';
import { isReactionsEnabled } from '../reactions/functions.any';
@ -92,10 +93,15 @@ export function getMoreTabProps(stateful: Object | Function) {
const language = i18next.language || DEFAULT_LANGUAGE;
const configuredTabs = interfaceConfig.SETTINGS_SECTIONS || [];
// when self view is controlled by the config we hide the settings
const { disableSelfView, disableSelfViewSettings } = state['features/base/config'];
return {
currentFramerate: framerate,
currentLanguage: language,
desktopShareFramerates: SS_SUPPORTED_FRAMERATES,
disableHideSelfView: disableSelfViewSettings || disableSelfView,
hideSelfView: getHideSelfView(state),
languages: LANGUAGES,
showLanguageSettings: configuredTabs.includes('language'),
showPrejoinPage: !state['features/base/settings'].userSelectedSkipPrejoin,
@ -159,13 +165,11 @@ export function getProfileTabProps(stateful: Object | Function) {
} = state['features/base/conference'];
const { hideEmailInSettings } = state['features/base/config'];
const localParticipant = getLocalParticipant(state);
const { disableSelfView } = state['features/base/settings'];
return {
authEnabled: Boolean(conference && authEnabled),
authLogin,
displayName: localParticipant.name,
disableSelfView: Boolean(disableSelfView),
email: localParticipant.email,
readOnlyName: isNameReadOnly(state),
hideEmailInSettings

View File

@ -0,0 +1,30 @@
import { MiddlewareRegistry } from '../base/redux';
import { getHideSelfView, SETTINGS_UPDATED } from '../base/settings';
import { NOTIFICATION_TIMEOUT_TYPE, showNotification } from '../notifications';
import { openSettingsDialog } from './actions';
import { SETTINGS_TABS } from './constants';
MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
const oldValue = getHideSelfView(getState());
const result = next(action);
switch (action.type) {
case SETTINGS_UPDATED: {
const newValue = action.settings.disableSelfView;
if (newValue !== oldValue && newValue) {
dispatch(showNotification({
titleKey: 'notify.selfViewTitle',
customActionNameKey: [ 'settings.title' ],
customActionHandler: [ () =>
dispatch(openSettingsDialog(SETTINGS_TABS.MORE))
]
}, NOTIFICATION_TIMEOUT_TYPE.STICKY));
}
}
}
return result;
});

View File

@ -8,6 +8,7 @@ import {
pinParticipant,
getParticipantCountWithFake
} from '../base/participants';
import { shouldHideSelfView } from '../base/settings/functions.any';
import {
ASPECT_RATIO_BREAKPOINT,
DEFAULT_MAX_COLUMNS,
@ -15,7 +16,6 @@ import {
SINGLE_COLUMN_BREAKPOINT,
TWO_COLUMN_BREAKPOINT
} from '../filmstrip/constants';
import { getDisableSelfView } from '../filmstrip/functions.any';
import { isVideoPlaying } from '../shared-video/functions';
import { LAYOUTS } from './constants';
@ -105,7 +105,7 @@ export function getTileViewGridDimensions(state: Object) {
// When in tile view mode, we must discount ourselves (the local participant) because our
// tile is not visible.
const { iAmRecorder } = state['features/base/config'];
const disableSelfView = getDisableSelfView(state);
const disableSelfView = shouldHideSelfView(state);
const numberOfParticipants = getParticipantCountWithFake(state)
- (iAmRecorder ? 1 : 0)
- (disableSelfView ? 1 : 0);

View File

@ -5,9 +5,7 @@ import React, { PureComponent } from 'react';
import ContextMenuItem from '../../../base/components/context-menu/ContextMenuItem';
import { translate } from '../../../base/i18n';
import { connect } from '../../../base/redux';
import { updateSettings } from '../../../base/settings';
import { NOTIFICATION_TIMEOUT_TYPE, showNotification } from '../../../notifications';
import { openSettingsDialog, SETTINGS_TABS } from '../../../settings';
import { getHideSelfView, updateSettings } from '../../../base/settings';
/**
* The type of the React {@code Component} props of {@link HideSelfViewVideoButton}.
@ -97,15 +95,6 @@ class HideSelfViewVideoButton extends PureComponent<Props> {
dispatch(updateSettings({
disableSelfView: !disableSelfView
}));
if (!disableSelfView) {
dispatch(showNotification({
titleKey: 'notify.selfViewTitle',
customActionNameKey: [ 'settings.title' ],
customActionHandler: [ () =>
dispatch(openSettingsDialog(SETTINGS_TABS.PROFILE))
]
}, NOTIFICATION_TIMEOUT_TYPE.STICKY));
}
}
}
@ -117,10 +106,8 @@ class HideSelfViewVideoButton extends PureComponent<Props> {
* @returns {Props}
*/
function _mapStateToProps(state) {
const { disableSelfView } = state['features/base/config'];
return {
disableSelfView: Boolean(disableSelfView)
disableSelfView: Boolean(getHideSelfView(state))
};
}

View File

@ -15,6 +15,7 @@ import {
import { Popover } from '../../../base/popover';
import { connect } from '../../../base/redux';
import { setParticipantContextMenuOpen } from '../../../base/responsive-ui/actions';
import { getHideSelfView } from '../../../base/settings';
import { getLocalVideoTrack } from '../../../base/tracks';
import ConnectionIndicatorContent from '../../../connection-indicator/components/web/ConnectionIndicatorContent';
import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
@ -82,6 +83,11 @@ type Props = {
*/
_showConnectionInfo: boolean,
/**
* Whether to render the hide self view button.
*/
_showHideSelfViewButton: boolean,
/**
* Shows/hides the local video flip button.
*/
@ -148,8 +154,9 @@ class LocalVideoMenuTriggerButton extends Component<Props> {
const {
_localParticipantId,
_menuPosition,
_showConnectionInfo,
_overflowDrawer,
_showConnectionInfo,
_showHideSelfViewButton,
_showLocalVideoFlipButton,
buttonVisible,
classes,
@ -169,9 +176,11 @@ class LocalVideoMenuTriggerButton extends Component<Props> {
<FlipLocalVideoButton
className = { _overflowDrawer ? classes.flipText : '' }
onClick = { hidePopover } />
<HideSelfViewVideoButton
className = { _overflowDrawer ? classes.flipText : '' }
onClick = { hidePopover } />
{ _showHideSelfViewButton
&& <HideSelfViewVideoButton
className = { _overflowDrawer ? classes.flipText : '' }
onClick = { hidePopover } />
}
{ isMobileBrowser()
&& <ConnectionStatusButton participantId = { _localParticipantId } />
}
@ -249,10 +258,11 @@ class LocalVideoMenuTriggerButton extends Component<Props> {
function _mapStateToProps(state) {
const currentLayout = getCurrentLayout(state);
const localParticipant = getLocalParticipant(state);
const { disableLocalVideoFlip } = state['features/base/config'];
const { disableLocalVideoFlip, disableSelfViewSettings } = state['features/base/config'];
const videoTrack = getLocalVideoTrack(state['features/base/tracks']);
const { overflowDrawer } = state['features/toolbox'];
const { showConnectionInfo } = state['features/base/connection'];
const showHideSelfViewButton = !disableSelfViewSettings && !getHideSelfView(state);
let _menuPosition;
@ -273,6 +283,7 @@ function _mapStateToProps(state) {
return {
_menuPosition,
_showLocalVideoFlipButton: !disableLocalVideoFlip && videoTrack?.videoType !== 'desktop',
_showHideSelfViewButton: showHideSelfViewButton,
_overflowDrawer: overflowDrawer,
_localParticipantId: localParticipant.id,
_showConnectionInfo: showConnectionInfo