fix(context-menus) Fix participant context menus/toolbar overflow menu
- on ipads, long touch open dialog now opens the context menu to the left of the thumbnail as expected - on ipads, now we close context menus on tap out - fix case when participant context menu's height > tileview videos' height causing scroll on videos pane - keep toolbox open while the overflow menu is shown - keep remote participant video thumbnail in filmstrip visible even if toolbox is hidden, if context menu is opened - Fix bug where toolbox could be completely disabled
This commit is contained in:
parent
1add438a1f
commit
b801e0115d
|
@ -54,4 +54,13 @@ export const CONNECTION_WILL_CONNECT = 'CONNECTION_WILL_CONNECT';
|
||||||
*/
|
*/
|
||||||
export const SET_LOCATION_URL = 'SET_LOCATION_URL';
|
export const SET_LOCATION_URL = 'SET_LOCATION_URL';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of (redux) action which tells whether connection info should be displayed
|
||||||
|
* on context menu.
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* type: SHOW_CONNECTION_INFO,
|
||||||
|
* showConnectionInfo: boolean
|
||||||
|
* }
|
||||||
|
*/
|
||||||
export const SHOW_CONNECTION_INFO = 'SHOW_CONNECTION_INFO';
|
export const SHOW_CONNECTION_INFO = 'SHOW_CONNECTION_INFO';
|
||||||
|
|
|
@ -113,6 +113,12 @@ class Popover extends Component<Props, State> {
|
||||||
id: ''
|
id: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to the dialog container.
|
||||||
|
*/
|
||||||
|
_containerRef: Object;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new {@code Popover} instance.
|
* Initializes a new {@code Popover} instance.
|
||||||
*
|
*
|
||||||
|
@ -130,8 +136,10 @@ class Popover extends Component<Props, State> {
|
||||||
this._onHideDialog = this._onHideDialog.bind(this);
|
this._onHideDialog = this._onHideDialog.bind(this);
|
||||||
this._onShowDialog = this._onShowDialog.bind(this);
|
this._onShowDialog = this._onShowDialog.bind(this);
|
||||||
this._onKeyPress = this._onKeyPress.bind(this);
|
this._onKeyPress = this._onKeyPress.bind(this);
|
||||||
|
this._containerRef = React.createRef();
|
||||||
this._onEscKey = this._onEscKey.bind(this);
|
this._onEscKey = this._onEscKey.bind(this);
|
||||||
this._onThumbClick = this._onThumbClick.bind(this);
|
this._onThumbClick = this._onThumbClick.bind(this);
|
||||||
|
this._onTouchStart = this._onTouchStart.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -141,7 +149,27 @@ class Popover extends Component<Props, State> {
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
showDialog() {
|
showDialog() {
|
||||||
this.setState({ showDialog: true });
|
this._onShowDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up a touch event listener to attach.
|
||||||
|
*
|
||||||
|
* @inheritdoc
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
componentDidMount() {
|
||||||
|
window.addEventListener('touchstart', this._onTouchStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the listener set up in the {@code componentDidMount} method.
|
||||||
|
*
|
||||||
|
* @inheritdoc
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
componentWillUnmount() {
|
||||||
|
window.removeEventListener('touchstart', this._onTouchStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -178,7 +206,8 @@ class Popover extends Component<Props, State> {
|
||||||
onClick = { this._onThumbClick }
|
onClick = { this._onThumbClick }
|
||||||
onKeyPress = { this._onKeyPress }
|
onKeyPress = { this._onKeyPress }
|
||||||
onMouseEnter = { this._onShowDialog }
|
onMouseEnter = { this._onShowDialog }
|
||||||
onMouseLeave = { this._onHideDialog }>
|
onMouseLeave = { this._onHideDialog }
|
||||||
|
ref = { this._containerRef }>
|
||||||
<InlineDialog
|
<InlineDialog
|
||||||
content = { this._renderContent() }
|
content = { this._renderContent() }
|
||||||
isOpen = { this.state.showDialog }
|
isOpen = { this.state.showDialog }
|
||||||
|
@ -189,6 +218,25 @@ class Popover extends Component<Props, State> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onTouchStart: (event: TouchEvent) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide dialog on touch outside of the context menu.
|
||||||
|
*
|
||||||
|
* @param {TouchEvent} event - The touch event.
|
||||||
|
* @private
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_onTouchStart(event) {
|
||||||
|
if (this.state.showDialog
|
||||||
|
&& !this.props.overflowDrawer
|
||||||
|
&& this._containerRef
|
||||||
|
&& this._containerRef.current
|
||||||
|
&& !this._containerRef.current.contains(event.target)) {
|
||||||
|
this._onHideDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_onHideDialog: () => void;
|
_onHideDialog: () => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -216,7 +264,7 @@ class Popover extends Component<Props, State> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onShowDialog(event) {
|
_onShowDialog(event) {
|
||||||
event.stopPropagation();
|
event && event.stopPropagation();
|
||||||
if (!this.props.disablePopover) {
|
if (!this.props.disablePopover) {
|
||||||
this.setState({ showDialog: true });
|
this.setState({ showDialog: true });
|
||||||
|
|
||||||
|
|
|
@ -30,3 +30,15 @@ export const SET_ASPECT_RATIO = 'SET_ASPECT_RATIO';
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export const SET_REDUCED_UI = 'SET_REDUCED_UI';
|
export const SET_REDUCED_UI = 'SET_REDUCED_UI';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of (redux) action which tells whether a local or remote participant
|
||||||
|
* context menu is open.
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* type: SET_CONTEXT_MENU_OPEN,
|
||||||
|
* showConnectionInfo: boolean
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
export const SET_CONTEXT_MENU_OPEN = 'SET_CONTEXT_MENU_OPEN';
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { CHAT_SIZE } from '../../chat/constants';
|
||||||
import { getParticipantsPaneOpen } from '../../participants-pane/functions';
|
import { getParticipantsPaneOpen } from '../../participants-pane/functions';
|
||||||
import theme from '../../participants-pane/theme.json';
|
import theme from '../../participants-pane/theme.json';
|
||||||
|
|
||||||
import { CLIENT_RESIZED, SET_ASPECT_RATIO, SET_REDUCED_UI } from './actionTypes';
|
import { CLIENT_RESIZED, SET_ASPECT_RATIO, SET_CONTEXT_MENU_OPEN, SET_REDUCED_UI } from './actionTypes';
|
||||||
import { ASPECT_RATIO_NARROW, ASPECT_RATIO_WIDE } from './constants';
|
import { ASPECT_RATIO_NARROW, ASPECT_RATIO_WIDE } from './constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,3 +110,16 @@ export function setReducedUI(width: number, height: number): Function {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the local or remote participant context menu is open.
|
||||||
|
*
|
||||||
|
* @param {boolean} isOpen - Whether local or remote context menu is open.
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
export function setParticipantContextMenuOpen(isOpen: boolean) {
|
||||||
|
return {
|
||||||
|
type: SET_CONTEXT_MENU_OPEN,
|
||||||
|
isOpen
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import { ReducerRegistry, set } from '../redux';
|
import { ReducerRegistry, set } from '../redux';
|
||||||
|
|
||||||
import { CLIENT_RESIZED, SET_ASPECT_RATIO, SET_REDUCED_UI } from './actionTypes';
|
import { CLIENT_RESIZED, SET_ASPECT_RATIO, SET_CONTEXT_MENU_OPEN, SET_REDUCED_UI } from './actionTypes';
|
||||||
import { ASPECT_RATIO_NARROW } from './constants';
|
import { ASPECT_RATIO_NARROW } from './constants';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -17,7 +17,8 @@ const DEFAULT_STATE = {
|
||||||
aspectRatio: ASPECT_RATIO_NARROW,
|
aspectRatio: ASPECT_RATIO_NARROW,
|
||||||
clientHeight: innerHeight,
|
clientHeight: innerHeight,
|
||||||
clientWidth: innerWidth,
|
clientWidth: innerWidth,
|
||||||
reducedUI: false
|
reducedUI: false,
|
||||||
|
contextMenuOpened: false
|
||||||
};
|
};
|
||||||
|
|
||||||
ReducerRegistry.register('features/base/responsive-ui', (state = DEFAULT_STATE, action) => {
|
ReducerRegistry.register('features/base/responsive-ui', (state = DEFAULT_STATE, action) => {
|
||||||
|
@ -34,6 +35,9 @@ ReducerRegistry.register('features/base/responsive-ui', (state = DEFAULT_STATE,
|
||||||
|
|
||||||
case SET_REDUCED_UI:
|
case SET_REDUCED_UI:
|
||||||
return set(state, 'reducedUI', action.reducedUI);
|
return set(state, 'reducedUI', action.reducedUI);
|
||||||
|
|
||||||
|
case SET_CONTEXT_MENU_OPEN:
|
||||||
|
return set(state, 'contextMenuOpened', action.isOpen);
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
|
|
|
@ -34,6 +34,11 @@ import ThumbnailWrapper from './ThumbnailWrapper';
|
||||||
declare var APP: Object;
|
declare var APP: Object;
|
||||||
declare var interfaceConfig: Object;
|
declare var interfaceConfig: Object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fixes case in which context menu overflows and creates a scroll on the whole filmstrip videos pane.
|
||||||
|
*/
|
||||||
|
const TILEVIEW_VIDEO_PANES_STYLE = { overflow: 'visible' };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the React {@code Component} props of {@link Filmstrip}.
|
* The type of the React {@code Component} props of {@link Filmstrip}.
|
||||||
*/
|
*/
|
||||||
|
@ -386,6 +391,7 @@ class Filmstrip extends PureComponent <Props> {
|
||||||
overscanRowCount = { 1 }
|
overscanRowCount = { 1 }
|
||||||
rowCount = { _rows }
|
rowCount = { _rows }
|
||||||
rowHeight = { _thumbnailHeight + TILE_VERTICAL_MARGIN }
|
rowHeight = { _thumbnailHeight + TILE_VERTICAL_MARGIN }
|
||||||
|
style = { TILEVIEW_VIDEO_PANES_STYLE }
|
||||||
width = { _filmstripWidth }>
|
width = { _filmstripWidth }>
|
||||||
{
|
{
|
||||||
ThumbnailWrapper
|
ThumbnailWrapper
|
||||||
|
|
|
@ -70,9 +70,11 @@ export function shouldRemoteVideosBeVisible(state: Object) {
|
||||||
const participantCount = getParticipantCountWithFake(state);
|
const participantCount = getParticipantCountWithFake(state);
|
||||||
let pinnedParticipant;
|
let pinnedParticipant;
|
||||||
const { disable1On1Mode } = state['features/base/config'];
|
const { disable1On1Mode } = state['features/base/config'];
|
||||||
|
const { contextMenuOpened } = state['features/base/responsive-ui'];
|
||||||
|
|
||||||
return Boolean(
|
return Boolean(
|
||||||
participantCount > 2
|
contextMenuOpened
|
||||||
|
|| participantCount > 2
|
||||||
|
|
||||||
// Always show the filmstrip when there is another participant to
|
// Always show the filmstrip when there is another participant to
|
||||||
// show and the local video is pinned, or the toolbar is displayed.
|
// show and the local video is pinned, or the toolbar is displayed.
|
||||||
|
|
|
@ -13,8 +13,7 @@ import {
|
||||||
clearToolboxTimeout,
|
clearToolboxTimeout,
|
||||||
setToolboxTimeout,
|
setToolboxTimeout,
|
||||||
setToolboxTimeoutMS,
|
setToolboxTimeoutMS,
|
||||||
setToolboxVisible,
|
setToolboxVisible
|
||||||
setToolboxEnabled
|
|
||||||
} from './actions.native';
|
} from './actions.native';
|
||||||
|
|
||||||
declare var interfaceConfig: Object;
|
declare var interfaceConfig: Object;
|
||||||
|
@ -132,10 +131,13 @@ export function showToolbox(timeout: number = 0): Object {
|
||||||
alwaysVisible,
|
alwaysVisible,
|
||||||
enabled,
|
enabled,
|
||||||
timeoutMS,
|
timeoutMS,
|
||||||
visible
|
visible,
|
||||||
|
overflowDrawer
|
||||||
} = state['features/toolbox'];
|
} = state['features/toolbox'];
|
||||||
|
const { contextMenuOpened } = state['features/base/responsive-ui'];
|
||||||
|
const contextMenuOpenedInTileview = isLayoutTileView(state) && contextMenuOpened && !overflowDrawer;
|
||||||
|
|
||||||
if (enabled && !visible) {
|
if (enabled && !visible && !contextMenuOpenedInTileview) {
|
||||||
dispatch(setToolboxVisible(true));
|
dispatch(setToolboxVisible(true));
|
||||||
|
|
||||||
// If the Toolbox is always visible, there's no need for a timeout
|
// If the Toolbox is always visible, there's no need for a timeout
|
||||||
|
@ -167,18 +169,20 @@ export function setOverflowDrawer(displayAsDrawer: boolean) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables and hides the toolbox on demand when in tile view.
|
* Disables and hides the toolbox on demand when in tile view.
|
||||||
*
|
*
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
export function disableToolboxOnTileView() {
|
export function hideToolboxOnTileView() {
|
||||||
return (dispatch: Dispatch<any>, getState: Function) => {
|
return (dispatch: Dispatch<any>, getState: Function) => {
|
||||||
if (!isLayoutTileView(getState())) {
|
const state = getState();
|
||||||
return;
|
const { overflowDrawer } = state['features/toolbox'];
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(setToolboxEnabled(false));
|
|
||||||
dispatch(hideToolbox(true));
|
if (!overflowDrawer && isLayoutTileView(state)) {
|
||||||
|
dispatch(hideToolbox(true));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -389,29 +389,27 @@ class Toolbox extends Component<Props, State> {
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
// Ensure the dialog is closed when the toolbox becomes hidden.
|
const { _dialog, _reactionsEnabled, _participantCount, dispatch, t } = this.props;
|
||||||
if (prevProps._overflowMenuVisible && !this.props._visible) {
|
|
||||||
this._onSetOverflowVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prevProps._overflowMenuVisible
|
if (prevProps._overflowMenuVisible
|
||||||
&& !prevProps._dialog
|
&& !prevProps._dialog
|
||||||
&& this.props._dialog) {
|
&& _dialog) {
|
||||||
this._onSetOverflowVisible(false);
|
this._onSetOverflowVisible(false);
|
||||||
this.props.dispatch(setToolbarHovered(false));
|
dispatch(setToolbarHovered(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.state.reactionsShortcutsRegistered
|
if (!this.state.reactionsShortcutsRegistered
|
||||||
&& (prevProps._reactionsEnabled !== this.props._reactionsEnabled
|
&& (prevProps._reactionsEnabled !== _reactionsEnabled
|
||||||
|| prevProps._participantCount !== this.props._participantCount)) {
|
|| prevProps._participantCount !== _participantCount)) {
|
||||||
if (this.props._reactionsEnabled && this.props._participantCount > 1) {
|
if (_reactionsEnabled && _participantCount > 1) {
|
||||||
// eslint-disable-next-line react/no-did-update-set-state
|
// eslint-disable-next-line react/no-did-update-set-state
|
||||||
this.setState({
|
this.setState({
|
||||||
reactionsShortcutsRegistered: true
|
reactionsShortcutsRegistered: true
|
||||||
});
|
});
|
||||||
const REACTION_SHORTCUTS = Object.keys(REACTIONS).map(key => {
|
const REACTION_SHORTCUTS = Object.keys(REACTIONS).map(key => {
|
||||||
const onShortcutSendReaction = () => {
|
const onShortcutSendReaction = () => {
|
||||||
this.props.dispatch(addReactionToBuffer(key));
|
dispatch(addReactionToBuffer(key));
|
||||||
sendAnalytics(createShortcutEvent(
|
sendAnalytics(createShortcutEvent(
|
||||||
`reaction.${key}`
|
`reaction.${key}`
|
||||||
));
|
));
|
||||||
|
@ -420,7 +418,7 @@ class Toolbox extends Component<Props, State> {
|
||||||
return {
|
return {
|
||||||
character: REACTIONS[key].shortcutChar,
|
character: REACTIONS[key].shortcutChar,
|
||||||
exec: onShortcutSendReaction,
|
exec: onShortcutSendReaction,
|
||||||
helpDescription: this.props.t(`toolbar.reaction${key.charAt(0).toUpperCase()}${key.slice(1)}`),
|
helpDescription: t(`toolbar.reaction${key.charAt(0).toUpperCase()}${key.slice(1)}`),
|
||||||
altKey: true
|
altKey: true
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -911,7 +909,9 @@ class Toolbox extends Component<Props, State> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onMouseOut() {
|
_onMouseOut() {
|
||||||
this.props.dispatch(setToolbarHovered(false));
|
const { _overflowMenuVisible, dispatch } = this.props;
|
||||||
|
|
||||||
|
!_overflowMenuVisible && dispatch(setToolbarHovered(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
_onMouseOver: () => void;
|
_onMouseOver: () => void;
|
||||||
|
@ -939,6 +939,7 @@ class Toolbox extends Component<Props, State> {
|
||||||
*/
|
*/
|
||||||
_onSetOverflowVisible(visible) {
|
_onSetOverflowVisible(visible) {
|
||||||
this.props.dispatch(setOverflowMenuVisible(visible));
|
this.props.dispatch(setOverflowMenuVisible(visible));
|
||||||
|
this.props.dispatch(setToolbarHovered(visible));
|
||||||
}
|
}
|
||||||
|
|
||||||
_onShortcutToggleChat: () => void;
|
_onShortcutToggleChat: () => void;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import { batch } from 'react-redux';
|
||||||
|
|
||||||
import { isMobileBrowser } from '../../../base/environment/utils';
|
import { isMobileBrowser } from '../../../base/environment/utils';
|
||||||
import { translate } from '../../../base/i18n';
|
import { translate } from '../../../base/i18n';
|
||||||
|
@ -10,10 +11,10 @@ import {
|
||||||
} from '../../../base/participants';
|
} from '../../../base/participants';
|
||||||
import { Popover } from '../../../base/popover';
|
import { Popover } from '../../../base/popover';
|
||||||
import { connect } from '../../../base/redux';
|
import { connect } from '../../../base/redux';
|
||||||
|
import { setParticipantContextMenuOpen } from '../../../base/responsive-ui/actions';
|
||||||
import { getLocalVideoTrack } from '../../../base/tracks';
|
import { getLocalVideoTrack } from '../../../base/tracks';
|
||||||
import ConnectionIndicatorContent from '../../../connection-indicator/components/web/ConnectionIndicatorContent';
|
import ConnectionIndicatorContent from '../../../connection-indicator/components/web/ConnectionIndicatorContent';
|
||||||
import { setToolboxEnabled, disableToolboxOnTileView } from '../../../toolbox/actions';
|
import { hideToolboxOnTileView } from '../../../toolbox/actions';
|
||||||
import { isToolboxEnabled } from '../../../toolbox/functions';
|
|
||||||
import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
|
import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
|
||||||
import { renderConnectionStatus } from '../../actions.web';
|
import { renderConnectionStatus } from '../../actions.web';
|
||||||
|
|
||||||
|
@ -65,11 +66,6 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
_showLocalVideoFlipButton: boolean,
|
_showLocalVideoFlipButton: boolean,
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the toolbox is enabled or not.
|
|
||||||
*/
|
|
||||||
_toolboxEnabled: boolean,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked to obtain translated strings.
|
* Invoked to obtain translated strings.
|
||||||
*/
|
*/
|
||||||
|
@ -83,11 +79,6 @@ type Props = {
|
||||||
* @extends {Component}
|
* @extends {Component}
|
||||||
*/
|
*/
|
||||||
class LocalVideoMenuTriggerButton extends Component<Props> {
|
class LocalVideoMenuTriggerButton extends Component<Props> {
|
||||||
/**
|
|
||||||
* Preserve the intial toolbox state.
|
|
||||||
*/
|
|
||||||
initialToolboxEnabled: boolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to the Popover instance.
|
* Reference to the Popover instance.
|
||||||
*/
|
*/
|
||||||
|
@ -103,7 +94,6 @@ class LocalVideoMenuTriggerButton extends Component<Props> {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.popoverRef = React.createRef();
|
this.popoverRef = React.createRef();
|
||||||
this.initialToolboxEnabled = true;
|
|
||||||
this._onPopoverClose = this._onPopoverClose.bind(this);
|
this._onPopoverClose = this._onPopoverClose.bind(this);
|
||||||
this._onPopoverOpen = this._onPopoverOpen.bind(this);
|
this._onPopoverOpen = this._onPopoverOpen.bind(this);
|
||||||
}
|
}
|
||||||
|
@ -129,8 +119,6 @@ class LocalVideoMenuTriggerButton extends Component<Props> {
|
||||||
if (this.props.getRef) {
|
if (this.props.getRef) {
|
||||||
this.props.getRef(this);
|
this.props.getRef(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initialToolboxEnabled = this.props._toolboxEnabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -181,16 +169,17 @@ class LocalVideoMenuTriggerButton extends Component<Props> {
|
||||||
overflowDrawer = { _overflowDrawer }
|
overflowDrawer = { _overflowDrawer }
|
||||||
position = { _menuPosition }
|
position = { _menuPosition }
|
||||||
ref = { this.popoverRef }>
|
ref = { this.popoverRef }>
|
||||||
{!isMobileBrowser() && (
|
{!_overflowDrawer && (
|
||||||
<span
|
<span
|
||||||
className = 'popover-trigger local-video-menu-trigger'>
|
className = 'popover-trigger local-video-menu-trigger'>
|
||||||
<Icon
|
{!isMobileBrowser() && <Icon
|
||||||
ariaLabel = { t('dialog.localUserControls') }
|
ariaLabel = { t('dialog.localUserControls') }
|
||||||
role = 'button'
|
role = 'button'
|
||||||
size = '1em'
|
size = '1em'
|
||||||
src = { IconMenuThumb }
|
src = { IconMenuThumb }
|
||||||
tabIndex = { 0 }
|
tabIndex = { 0 }
|
||||||
title = { t('dialog.localUserControls') } />
|
title = { t('dialog.localUserControls') } />
|
||||||
|
}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</Popover>
|
</Popover>
|
||||||
|
@ -206,7 +195,8 @@ class LocalVideoMenuTriggerButton extends Component<Props> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onPopoverOpen() {
|
_onPopoverOpen() {
|
||||||
this.props.dispatch(disableToolboxOnTileView());
|
this.props.dispatch(setParticipantContextMenuOpen(true));
|
||||||
|
this.props.dispatch(hideToolboxOnTileView());
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPopoverClose: () => void;
|
_onPopoverClose: () => void;
|
||||||
|
@ -217,8 +207,12 @@ class LocalVideoMenuTriggerButton extends Component<Props> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onPopoverClose() {
|
_onPopoverClose() {
|
||||||
this.props.dispatch(setToolboxEnabled(this.initialToolboxEnabled));
|
const { dispatch } = this.props;
|
||||||
this.props.dispatch(renderConnectionStatus(false));
|
|
||||||
|
batch(() => {
|
||||||
|
dispatch(setParticipantContextMenuOpen(false));
|
||||||
|
dispatch(renderConnectionStatus(false));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,8 +252,7 @@ function _mapStateToProps(state) {
|
||||||
_showLocalVideoFlipButton: !disableLocalVideoFlip && videoTrack?.videoType !== 'desktop',
|
_showLocalVideoFlipButton: !disableLocalVideoFlip && videoTrack?.videoType !== 'desktop',
|
||||||
_overflowDrawer: overflowDrawer,
|
_overflowDrawer: overflowDrawer,
|
||||||
_localParticipantId: localParticipant.id,
|
_localParticipantId: localParticipant.id,
|
||||||
_showConnectionInfo: showConnectionInfo,
|
_showConnectionInfo: showConnectionInfo
|
||||||
_toolboxEnabled: isToolboxEnabled(state)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import { batch } from 'react-redux';
|
||||||
|
|
||||||
import ConnectionIndicatorContent from
|
import ConnectionIndicatorContent from
|
||||||
'../../../../features/connection-indicator/components/web/ConnectionIndicatorContent';
|
'../../../../features/connection-indicator/components/web/ConnectionIndicatorContent';
|
||||||
|
@ -10,9 +11,9 @@ import { Icon, IconMenuThumb } from '../../../base/icons';
|
||||||
import { getLocalParticipant, getParticipantById, PARTICIPANT_ROLE } from '../../../base/participants';
|
import { getLocalParticipant, getParticipantById, PARTICIPANT_ROLE } from '../../../base/participants';
|
||||||
import { Popover } from '../../../base/popover';
|
import { Popover } from '../../../base/popover';
|
||||||
import { connect } from '../../../base/redux';
|
import { connect } from '../../../base/redux';
|
||||||
|
import { setParticipantContextMenuOpen } from '../../../base/responsive-ui/actions';
|
||||||
import { requestRemoteControl, stopController } from '../../../remote-control';
|
import { requestRemoteControl, stopController } from '../../../remote-control';
|
||||||
import { setToolboxEnabled, disableToolboxOnTileView } from '../../../toolbox/actions';
|
import { hideToolboxOnTileView } from '../../../toolbox/actions';
|
||||||
import { isToolboxEnabled } from '../../../toolbox/functions';
|
|
||||||
import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
|
import { getCurrentLayout, LAYOUTS } from '../../../video-layout';
|
||||||
import { renderConnectionStatus } from '../../actions.web';
|
import { renderConnectionStatus } from '../../actions.web';
|
||||||
|
|
||||||
|
@ -78,11 +79,6 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
_remoteControlState: number,
|
_remoteControlState: number,
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the toolbox is enabled or not.
|
|
||||||
*/
|
|
||||||
_toolboxEnabled: boolean,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The redux dispatch function.
|
* The redux dispatch function.
|
||||||
*/
|
*/
|
||||||
|
@ -133,11 +129,6 @@ type Props = {
|
||||||
* @extends {Component}
|
* @extends {Component}
|
||||||
*/
|
*/
|
||||||
class RemoteVideoMenuTriggerButton extends Component<Props> {
|
class RemoteVideoMenuTriggerButton extends Component<Props> {
|
||||||
/**
|
|
||||||
* Preserve the intial toolbox state.
|
|
||||||
*/
|
|
||||||
initialToolboxEnabled: boolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to the Popover instance.
|
* Reference to the Popover instance.
|
||||||
*/
|
*/
|
||||||
|
@ -153,7 +144,6 @@ class RemoteVideoMenuTriggerButton extends Component<Props> {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.popoverRef = React.createRef();
|
this.popoverRef = React.createRef();
|
||||||
this.initialToolboxEnabled = true;
|
|
||||||
this._onPopoverClose = this._onPopoverClose.bind(this);
|
this._onPopoverClose = this._onPopoverClose.bind(this);
|
||||||
this._onPopoverOpen = this._onPopoverOpen.bind(this);
|
this._onPopoverOpen = this._onPopoverOpen.bind(this);
|
||||||
}
|
}
|
||||||
|
@ -179,8 +169,6 @@ class RemoteVideoMenuTriggerButton extends Component<Props> {
|
||||||
if (this.props.getRef) {
|
if (this.props.getRef) {
|
||||||
this.props.getRef(this);
|
this.props.getRef(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initialToolboxEnabled = this.props._toolboxEnabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -202,7 +190,7 @@ class RemoteVideoMenuTriggerButton extends Component<Props> {
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const { _showConnectionInfo, _participantDisplayName, participantID } = this.props;
|
const { _overflowDrawer, _showConnectionInfo, _participantDisplayName, participantID } = this.props;
|
||||||
const content = _showConnectionInfo
|
const content = _showConnectionInfo
|
||||||
? <ConnectionIndicatorContent participantId = { participantID } />
|
? <ConnectionIndicatorContent participantId = { participantID } />
|
||||||
: this._renderRemoteVideoMenu();
|
: this._renderRemoteVideoMenu();
|
||||||
|
@ -218,18 +206,19 @@ class RemoteVideoMenuTriggerButton extends Component<Props> {
|
||||||
content = { content }
|
content = { content }
|
||||||
onPopoverClose = { this._onPopoverClose }
|
onPopoverClose = { this._onPopoverClose }
|
||||||
onPopoverOpen = { this._onPopoverOpen }
|
onPopoverOpen = { this._onPopoverOpen }
|
||||||
overflowDrawer = { this.props._overflowDrawer }
|
overflowDrawer = { _overflowDrawer }
|
||||||
position = { this.props._menuPosition }
|
position = { this.props._menuPosition }
|
||||||
ref = { this.popoverRef }>
|
ref = { this.popoverRef }>
|
||||||
{!isMobileBrowser() && (
|
{!_overflowDrawer && (
|
||||||
<span className = 'popover-trigger remote-video-menu-trigger'>
|
<span className = 'popover-trigger remote-video-menu-trigger'>
|
||||||
<Icon
|
{!isMobileBrowser() && <Icon
|
||||||
ariaLabel = { this.props.t('dialog.remoteUserControls', { username }) }
|
ariaLabel = { this.props.t('dialog.remoteUserControls', { username }) }
|
||||||
role = 'button'
|
role = 'button'
|
||||||
size = '1.4em'
|
size = '1.4em'
|
||||||
src = { IconMenuThumb }
|
src = { IconMenuThumb }
|
||||||
tabIndex = { 0 }
|
tabIndex = { 0 }
|
||||||
title = { this.props.t('dialog.remoteUserControls', { username }) } />
|
title = { this.props.t('dialog.remoteUserControls', { username }) } />
|
||||||
|
}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</Popover>
|
</Popover>
|
||||||
|
@ -244,7 +233,8 @@ class RemoteVideoMenuTriggerButton extends Component<Props> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onPopoverOpen() {
|
_onPopoverOpen() {
|
||||||
this.props.dispatch(disableToolboxOnTileView());
|
this.props.dispatch(setParticipantContextMenuOpen(true));
|
||||||
|
this.props.dispatch(hideToolboxOnTileView());
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPopoverClose: () => void;
|
_onPopoverClose: () => void;
|
||||||
|
@ -255,8 +245,12 @@ class RemoteVideoMenuTriggerButton extends Component<Props> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onPopoverClose() {
|
_onPopoverClose() {
|
||||||
this.props.dispatch(setToolboxEnabled(this.initialToolboxEnabled));
|
const { dispatch } = this.props;
|
||||||
this.props.dispatch(renderConnectionStatus(false));
|
|
||||||
|
batch(() => {
|
||||||
|
dispatch(setParticipantContextMenuOpen(false));
|
||||||
|
dispatch(renderConnectionStatus(false));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -349,6 +343,7 @@ class RemoteVideoMenuTriggerButton extends Component<Props> {
|
||||||
if (isMobileBrowser()) {
|
if (isMobileBrowser()) {
|
||||||
buttons.push(
|
buttons.push(
|
||||||
<ConnectionStatusButton
|
<ConnectionStatusButton
|
||||||
|
key = 'conn-status'
|
||||||
participantId = { participantID } />
|
participantId = { participantID } />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -435,8 +430,7 @@ function _mapStateToProps(state, ownProps) {
|
||||||
_overflowDrawer: overflowDrawer,
|
_overflowDrawer: overflowDrawer,
|
||||||
_participantDisplayName,
|
_participantDisplayName,
|
||||||
_disableGrantModerator: Boolean(disableGrantModerator),
|
_disableGrantModerator: Boolean(disableGrantModerator),
|
||||||
_showConnectionInfo: showConnectionInfo,
|
_showConnectionInfo: showConnectionInfo
|
||||||
_toolboxEnabled: isToolboxEnabled(state)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue