fix(reactions) Moved reactions behind feature flag
This commit is contained in:
parent
2209394d09
commit
2d04f3852c
|
@ -70,6 +70,9 @@ var config = {
|
||||||
// callStatsThreshold: 5 // enable callstats for 5% of the users.
|
// callStatsThreshold: 5 // enable callstats for 5% of the users.
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Enables reactions feature.
|
||||||
|
enableReactions: false,
|
||||||
|
|
||||||
// Disables ICE/UDP by filtering out local and remote UDP candidates in
|
// Disables ICE/UDP by filtering out local and remote UDP candidates in
|
||||||
// signalling.
|
// signalling.
|
||||||
// webrtcIceUdpDisable: false,
|
// webrtcIceUdpDisable: false,
|
||||||
|
|
|
@ -90,7 +90,7 @@
|
||||||
width: 20%;
|
width: 20%;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 40%;
|
left: 40%;
|
||||||
height: 48px;
|
height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reactions-menu-popup-container,
|
.reactions-menu-popup-container,
|
||||||
|
@ -111,8 +111,8 @@ $reactionCount: 20;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
top: 32px;
|
top: 0;
|
||||||
left: 10px;
|
left: 20px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
|
@ -123,8 +123,8 @@ $reactionCount: 20;
|
||||||
@for $i from 1 through $reactionCount {
|
@for $i from 1 through $reactionCount {
|
||||||
&.reaction-#{$i} {
|
&.reaction-#{$i} {
|
||||||
animation: animation-#{$i} 5s forwards ease-in-out;
|
animation: animation-#{$i} 5s forwards ease-in-out;
|
||||||
top: #{random(50, 0)}px;
|
top: #{random(-40, 10)}px;
|
||||||
left: #{random(-10, 10)}px;
|
left: #{random(0, 30)}px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,3 +214,9 @@ export const VIDEO_SHARE_BUTTON_ENABLED = 'video-share.enabled';
|
||||||
* Default: disabled (false).
|
* Default: disabled (false).
|
||||||
*/
|
*/
|
||||||
export const WELCOME_PAGE_ENABLED = 'welcomepage.enabled';
|
export const WELCOME_PAGE_ENABLED = 'welcomepage.enabled';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag indicating if the reactions feature should be enabled.
|
||||||
|
* Default: disabled (false).
|
||||||
|
*/
|
||||||
|
export const REACTIONS_ENABLED = 'reactions.enabled';
|
||||||
|
|
|
@ -4,6 +4,7 @@ import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
import { ColorSchemeRegistry } from '../../../base/color-scheme';
|
import { ColorSchemeRegistry } from '../../../base/color-scheme';
|
||||||
import { BottomSheet, hideDialog, isDialogOpen } from '../../../base/dialog';
|
import { BottomSheet, hideDialog, isDialogOpen } from '../../../base/dialog';
|
||||||
|
import { getFeatureFlag, REACTIONS_ENABLED } from '../../../base/flags';
|
||||||
import { connect } from '../../../base/redux';
|
import { connect } from '../../../base/redux';
|
||||||
import { StyleType } from '../../../base/styles';
|
import { StyleType } from '../../../base/styles';
|
||||||
import { SharedDocumentButton } from '../../../etherpad';
|
import { SharedDocumentButton } from '../../../etherpad';
|
||||||
|
@ -22,6 +23,7 @@ import MuteEveryoneButton from '../MuteEveryoneButton';
|
||||||
import MuteEveryonesVideoButton from '../MuteEveryonesVideoButton';
|
import MuteEveryonesVideoButton from '../MuteEveryonesVideoButton';
|
||||||
|
|
||||||
import AudioOnlyButton from './AudioOnlyButton';
|
import AudioOnlyButton from './AudioOnlyButton';
|
||||||
|
import RaiseHandButton from './RaiseHandButton';
|
||||||
import ScreenSharingButton from './ScreenSharingButton.js';
|
import ScreenSharingButton from './ScreenSharingButton.js';
|
||||||
import ToggleCameraButton from './ToggleCameraButton';
|
import ToggleCameraButton from './ToggleCameraButton';
|
||||||
|
|
||||||
|
@ -50,6 +52,11 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
_width: number,
|
_width: number,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the reactions feature is enabled.
|
||||||
|
*/
|
||||||
|
_reactionsEnabled: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for hiding the dialog when the selection was completed.
|
* Used for hiding the dialog when the selection was completed.
|
||||||
*/
|
*/
|
||||||
|
@ -102,7 +109,7 @@ class OverflowMenu extends PureComponent<Props, State> {
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const { _bottomSheetStyles, _width } = this.props;
|
const { _bottomSheetStyles, _width, _reactionsEnabled } = this.props;
|
||||||
const toolbarButtons = getMovableButtons(_width);
|
const toolbarButtons = getMovableButtons(_width);
|
||||||
|
|
||||||
const buttonProps = {
|
const buttonProps = {
|
||||||
|
@ -128,13 +135,14 @@ class OverflowMenu extends PureComponent<Props, State> {
|
||||||
return (
|
return (
|
||||||
<BottomSheet
|
<BottomSheet
|
||||||
onCancel = { this._onCancel }
|
onCancel = { this._onCancel }
|
||||||
renderFooter = { toolbarButtons.has('raisehand')
|
renderFooter = { _reactionsEnabled && !toolbarButtons.has('raisehand')
|
||||||
? null
|
? this._renderReactionMenu
|
||||||
: this._renderReactionMenu }>
|
: null }>
|
||||||
<AudioRouteButton { ...topButtonProps } />
|
<AudioRouteButton { ...topButtonProps } />
|
||||||
<ParticipantsPaneButton { ...buttonProps } />
|
<ParticipantsPaneButton { ...buttonProps } />
|
||||||
{!toolbarButtons.has('invite') && <InviteButton { ...buttonProps } />}
|
{!toolbarButtons.has('invite') && <InviteButton { ...buttonProps } />}
|
||||||
<AudioOnlyButton { ...buttonProps } />
|
<AudioOnlyButton { ...buttonProps } />
|
||||||
|
{!_reactionsEnabled && !toolbarButtons.has('raisehand') && <RaiseHandButton { ...buttonProps } />}
|
||||||
<SecurityDialogButton { ...buttonProps } />
|
<SecurityDialogButton { ...buttonProps } />
|
||||||
<ScreenSharingButton { ...buttonProps } />
|
<ScreenSharingButton { ...buttonProps } />
|
||||||
{!toolbarButtons.has('togglecamera') && <ToggleCameraButton { ...buttonProps } />}
|
{!toolbarButtons.has('togglecamera') && <ToggleCameraButton { ...buttonProps } />}
|
||||||
|
@ -194,7 +202,8 @@ function _mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
_bottomSheetStyles: ColorSchemeRegistry.get(state, 'BottomSheet'),
|
_bottomSheetStyles: ColorSchemeRegistry.get(state, 'BottomSheet'),
|
||||||
_isOpen: isDialogOpen(state, OverflowMenu_),
|
_isOpen: isDialogOpen(state, OverflowMenu_),
|
||||||
_width: state['features/base/responsive-ui'].clientWidth
|
_width: state['features/base/responsive-ui'].clientWidth,
|
||||||
|
_reactionsEnabled: getFeatureFlag(state, REACTIONS_ENABLED, false)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { type Dispatch } from 'redux';
|
||||||
|
|
||||||
|
import {
|
||||||
|
createToolbarEvent,
|
||||||
|
sendAnalytics
|
||||||
|
} from '../../../analytics';
|
||||||
|
import { RAISE_HAND_ENABLED, getFeatureFlag } from '../../../base/flags';
|
||||||
|
import { translate } from '../../../base/i18n';
|
||||||
|
import { IconRaisedHand } from '../../../base/icons';
|
||||||
|
import {
|
||||||
|
getLocalParticipant,
|
||||||
|
raiseHand
|
||||||
|
} from '../../../base/participants';
|
||||||
|
import { connect } from '../../../base/redux';
|
||||||
|
import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the React {@code Component} props of {@link RaiseHandButton}.
|
||||||
|
*/
|
||||||
|
type Props = AbstractButtonProps & {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The local participant.
|
||||||
|
*/
|
||||||
|
_localParticipant: Object,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the participant raused their hand or not.
|
||||||
|
*/
|
||||||
|
_raisedHand: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The redux {@code dispatch} function.
|
||||||
|
*/
|
||||||
|
dispatch: Dispatch<any>
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of a button to raise or lower hand.
|
||||||
|
*/
|
||||||
|
class RaiseHandButton extends AbstractButton<Props, *> {
|
||||||
|
accessibilityLabel = 'toolbar.accessibilityLabel.raiseHand';
|
||||||
|
icon = IconRaisedHand;
|
||||||
|
label = 'toolbar.raiseYourHand';
|
||||||
|
toggledLabel = 'toolbar.lowerYourHand';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles clicking / pressing the button.
|
||||||
|
*
|
||||||
|
* @override
|
||||||
|
* @protected
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_handleClick() {
|
||||||
|
this._toggleRaisedHand();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether this button is in toggled state or not.
|
||||||
|
*
|
||||||
|
* @override
|
||||||
|
* @protected
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
_isToggled() {
|
||||||
|
return this.props._raisedHand;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles the rased hand status of the local participant.
|
||||||
|
*
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_toggleRaisedHand() {
|
||||||
|
const enable = !this.props._raisedHand;
|
||||||
|
|
||||||
|
sendAnalytics(createToolbarEvent('raise.hand', { enable }));
|
||||||
|
|
||||||
|
this.props.dispatch(raiseHand(enable));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps part of the Redux state to the props of this component.
|
||||||
|
*
|
||||||
|
* @param {Object} state - The Redux state.
|
||||||
|
* @param {Object} ownProps - The properties explicitly passed to the component instance.
|
||||||
|
* @private
|
||||||
|
* @returns {Props}
|
||||||
|
*/
|
||||||
|
function _mapStateToProps(state, ownProps): Object {
|
||||||
|
const _localParticipant = getLocalParticipant(state);
|
||||||
|
const enabled = getFeatureFlag(state, RAISE_HAND_ENABLED, true);
|
||||||
|
const { visible = enabled } = ownProps;
|
||||||
|
|
||||||
|
return {
|
||||||
|
_localParticipant,
|
||||||
|
_raisedHand: _localParticipant.raisedHand,
|
||||||
|
visible
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default translate(connect(_mapStateToProps)(RaiseHandButton));
|
|
@ -4,6 +4,7 @@ import React from 'react';
|
||||||
import { SafeAreaView, View } from 'react-native';
|
import { SafeAreaView, View } from 'react-native';
|
||||||
|
|
||||||
import { ColorSchemeRegistry } from '../../../base/color-scheme';
|
import { ColorSchemeRegistry } from '../../../base/color-scheme';
|
||||||
|
import { getFeatureFlag, REACTIONS_ENABLED } from '../../../base/flags';
|
||||||
import { connect } from '../../../base/redux';
|
import { connect } from '../../../base/redux';
|
||||||
import { StyleType } from '../../../base/styles';
|
import { StyleType } from '../../../base/styles';
|
||||||
import { ChatButton } from '../../../chat';
|
import { ChatButton } from '../../../chat';
|
||||||
|
@ -16,6 +17,7 @@ import HangupButton from '../HangupButton';
|
||||||
import VideoMuteButton from '../VideoMuteButton';
|
import VideoMuteButton from '../VideoMuteButton';
|
||||||
|
|
||||||
import OverflowMenuButton from './OverflowMenuButton';
|
import OverflowMenuButton from './OverflowMenuButton';
|
||||||
|
import RaiseHandButton from './RaiseHandButton';
|
||||||
import ToggleCameraButton from './ToggleCameraButton';
|
import ToggleCameraButton from './ToggleCameraButton';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
||||||
|
@ -39,6 +41,11 @@ type Props = {
|
||||||
*/
|
*/
|
||||||
_width: number,
|
_width: number,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the reactions feature is enabled.
|
||||||
|
*/
|
||||||
|
_reactionsEnabled: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The redux {@code dispatch} function.
|
* The redux {@code dispatch} function.
|
||||||
*/
|
*/
|
||||||
|
@ -56,7 +63,7 @@ function Toolbox(props: Props) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { _styles, _width } = props;
|
const { _styles, _width, _reactionsEnabled } = props;
|
||||||
const { buttonStylesBorderless, hangupButtonStyles, toggledButtonStyles } = _styles;
|
const { buttonStylesBorderless, hangupButtonStyles, toggledButtonStyles } = _styles;
|
||||||
const additionalButtons = getMovableButtons(_width);
|
const additionalButtons = getMovableButtons(_width);
|
||||||
const backgroundToggledStyle = {
|
const backgroundToggledStyle = {
|
||||||
|
@ -86,10 +93,13 @@ function Toolbox(props: Props) {
|
||||||
styles = { buttonStylesBorderless }
|
styles = { buttonStylesBorderless }
|
||||||
toggledStyles = { backgroundToggledStyle } />}
|
toggledStyles = { backgroundToggledStyle } />}
|
||||||
|
|
||||||
{ additionalButtons.has('raisehand')
|
{ additionalButtons.has('raisehand') && (_reactionsEnabled
|
||||||
&& <ReactionsMenuButton
|
? <ReactionsMenuButton
|
||||||
styles = { buttonStylesBorderless }
|
styles = { buttonStylesBorderless }
|
||||||
toggledStyles = { backgroundToggledStyle } />}
|
toggledStyles = { backgroundToggledStyle } />
|
||||||
|
: <RaiseHandButton
|
||||||
|
styles = { buttonStylesBorderless }
|
||||||
|
toggledStyles = { backgroundToggledStyle } />)}
|
||||||
{additionalButtons.has('tileview') && <TileViewButton styles = { buttonStylesBorderless } />}
|
{additionalButtons.has('tileview') && <TileViewButton styles = { buttonStylesBorderless } />}
|
||||||
{additionalButtons.has('invite') && <InviteButton styles = { buttonStylesBorderless } />}
|
{additionalButtons.has('invite') && <InviteButton styles = { buttonStylesBorderless } />}
|
||||||
{additionalButtons.has('togglecamera')
|
{additionalButtons.has('togglecamera')
|
||||||
|
@ -119,7 +129,8 @@ function _mapStateToProps(state: Object): Object {
|
||||||
return {
|
return {
|
||||||
_styles: ColorSchemeRegistry.get(state, 'Toolbox'),
|
_styles: ColorSchemeRegistry.get(state, 'Toolbox'),
|
||||||
_visible: isToolboxVisible(state),
|
_visible: isToolboxVisible(state),
|
||||||
_width: state['features/base/responsive-ui'].clientWidth
|
_width: state['features/base/responsive-ui'].clientWidth,
|
||||||
|
_reactionsEnabled: getFeatureFlag(state, REACTIONS_ENABLED, false)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { translate } from '../../../base/i18n';
|
||||||
|
import { IconRaisedHand } from '../../../base/icons';
|
||||||
|
import { getLocalParticipant } from '../../../base/participants';
|
||||||
|
import { connect } from '../../../base/redux';
|
||||||
|
import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
|
||||||
|
|
||||||
|
type Props = AbstractButtonProps & {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the local participant's hand is raised.
|
||||||
|
*/
|
||||||
|
_raisedHand: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External handler for click action.
|
||||||
|
*/
|
||||||
|
handleClick: Function
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of a button for toggling raise hand functionality.
|
||||||
|
*/
|
||||||
|
class RaiseHandButton extends AbstractButton<Props, *> {
|
||||||
|
accessibilityLabel = 'toolbar.accessibilityLabel.raiseHand';
|
||||||
|
icon = IconRaisedHand
|
||||||
|
label = 'toolbar.raiseYourHand';
|
||||||
|
toggledLabel = 'toolbar.lowerYourHand'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves tooltip dynamically.
|
||||||
|
*/
|
||||||
|
get tooltip() {
|
||||||
|
return this.props._raisedHand ? 'toolbar.lowerYourHand' : 'toolbar.raiseYourHand';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required by linter due to AbstractButton overwritten prop being writable.
|
||||||
|
*
|
||||||
|
* @param {string} value - The value.
|
||||||
|
*/
|
||||||
|
set tooltip(value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles clicking / pressing the button, and opens the appropriate dialog.
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_handleClick() {
|
||||||
|
this.props.handleClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether this button is in toggled state or not.
|
||||||
|
*
|
||||||
|
* @override
|
||||||
|
* @protected
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
_isToggled() {
|
||||||
|
return this.props._raisedHand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that maps parts of Redux state tree into component props.
|
||||||
|
*
|
||||||
|
* @param {Object} state - Redux state.
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
const localParticipant = getLocalParticipant(state);
|
||||||
|
|
||||||
|
return {
|
||||||
|
_raisedHand: localParticipant.raisedHand
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default translate(connect(mapStateToProps)(RaiseHandButton));
|
|
@ -85,6 +85,7 @@ import AudioSettingsButton from './AudioSettingsButton';
|
||||||
import FullscreenButton from './FullscreenButton';
|
import FullscreenButton from './FullscreenButton';
|
||||||
import OverflowMenuButton from './OverflowMenuButton';
|
import OverflowMenuButton from './OverflowMenuButton';
|
||||||
import ProfileButton from './ProfileButton';
|
import ProfileButton from './ProfileButton';
|
||||||
|
import RaiseHandButton from './RaiseHandButton';
|
||||||
import Separator from './Separator';
|
import Separator from './Separator';
|
||||||
import ShareDesktopButton from './ShareDesktopButton';
|
import ShareDesktopButton from './ShareDesktopButton';
|
||||||
import VideoSettingsButton from './VideoSettingsButton';
|
import VideoSettingsButton from './VideoSettingsButton';
|
||||||
|
@ -213,7 +214,12 @@ type Props = {
|
||||||
/**
|
/**
|
||||||
* Returns the selected virtual source object.
|
* Returns the selected virtual source object.
|
||||||
*/
|
*/
|
||||||
_virtualSource: Object,
|
_virtualSource: Object,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not reactions feature is enabled.
|
||||||
|
*/
|
||||||
|
_reactionsEnabled: boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked to active other features of the app.
|
* Invoked to active other features of the app.
|
||||||
|
@ -259,6 +265,7 @@ class Toolbox extends Component<Props> {
|
||||||
this._onToolbarOpenVideoQuality = this._onToolbarOpenVideoQuality.bind(this);
|
this._onToolbarOpenVideoQuality = this._onToolbarOpenVideoQuality.bind(this);
|
||||||
this._onToolbarToggleChat = this._onToolbarToggleChat.bind(this);
|
this._onToolbarToggleChat = this._onToolbarToggleChat.bind(this);
|
||||||
this._onToolbarToggleFullScreen = this._onToolbarToggleFullScreen.bind(this);
|
this._onToolbarToggleFullScreen = this._onToolbarToggleFullScreen.bind(this);
|
||||||
|
this._onToolbarToggleRaiseHand = this._onToolbarToggleRaiseHand.bind(this);
|
||||||
this._onToolbarToggleScreenshare = this._onToolbarToggleScreenshare.bind(this);
|
this._onToolbarToggleScreenshare = this._onToolbarToggleScreenshare.bind(this);
|
||||||
this._onShortcutToggleTileView = this._onShortcutToggleTileView.bind(this);
|
this._onShortcutToggleTileView = this._onShortcutToggleTileView.bind(this);
|
||||||
this._onEscKey = this._onEscKey.bind(this);
|
this._onEscKey = this._onEscKey.bind(this);
|
||||||
|
@ -271,7 +278,7 @@ class Toolbox extends Component<Props> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { _toolbarButtons, t, dispatch } = this.props;
|
const { _toolbarButtons, t, dispatch, _reactionsEnabled } = this.props;
|
||||||
const KEYBOARD_SHORTCUTS = [
|
const KEYBOARD_SHORTCUTS = [
|
||||||
isToolbarButtonEnabled('videoquality', _toolbarButtons) && {
|
isToolbarButtonEnabled('videoquality', _toolbarButtons) && {
|
||||||
character: 'A',
|
character: 'A',
|
||||||
|
@ -320,30 +327,32 @@ class Toolbox extends Component<Props> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const REACTION_SHORTCUTS = Object.keys(REACTIONS).map(key => {
|
if (_reactionsEnabled) {
|
||||||
const onShortcutSendReaction = () => {
|
const REACTION_SHORTCUTS = Object.keys(REACTIONS).map(key => {
|
||||||
dispatch(addReactionToBuffer(key));
|
const onShortcutSendReaction = () => {
|
||||||
sendAnalytics(createShortcutEvent(
|
dispatch(addReactionToBuffer(key));
|
||||||
`reaction.${key}`
|
sendAnalytics(createShortcutEvent(
|
||||||
));
|
`reaction.${key}`
|
||||||
};
|
));
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
character: REACTIONS[key].shortcutChar,
|
character: REACTIONS[key].shortcutChar,
|
||||||
exec: onShortcutSendReaction,
|
exec: onShortcutSendReaction,
|
||||||
helpDescription: 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
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
REACTION_SHORTCUTS.forEach(shortcut => {
|
REACTION_SHORTCUTS.forEach(shortcut => {
|
||||||
APP.keyboardshortcut.registerShortcut(
|
APP.keyboardshortcut.registerShortcut(
|
||||||
shortcut.character,
|
shortcut.character,
|
||||||
null,
|
null,
|
||||||
shortcut.exec,
|
shortcut.exec,
|
||||||
shortcut.helpDescription,
|
shortcut.helpDescription,
|
||||||
shortcut.altKey);
|
shortcut.altKey);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -375,9 +384,11 @@ class Toolbox extends Component<Props> {
|
||||||
[ 'A', 'C', 'D', 'R', 'S' ].forEach(letter =>
|
[ 'A', 'C', 'D', 'R', 'S' ].forEach(letter =>
|
||||||
APP.keyboardshortcut.unregisterShortcut(letter));
|
APP.keyboardshortcut.unregisterShortcut(letter));
|
||||||
|
|
||||||
Object.keys(REACTIONS).map(key => REACTIONS[key].shortcutChar)
|
if (this.props._reactionsEnabled) {
|
||||||
.forEach(letter =>
|
Object.keys(REACTIONS).map(key => REACTIONS[key].shortcutChar)
|
||||||
APP.keyboardshortcut.unregisterShortcut(letter, true));
|
.forEach(letter =>
|
||||||
|
APP.keyboardshortcut.unregisterShortcut(letter, true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -541,7 +552,8 @@ class Toolbox extends Component<Props> {
|
||||||
const {
|
const {
|
||||||
_feedbackConfigured,
|
_feedbackConfigured,
|
||||||
_isMobile,
|
_isMobile,
|
||||||
_screenSharing
|
_screenSharing,
|
||||||
|
_reactionsEnabled
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const microphone = {
|
const microphone = {
|
||||||
|
@ -578,7 +590,8 @@ class Toolbox extends Component<Props> {
|
||||||
|
|
||||||
const raisehand = {
|
const raisehand = {
|
||||||
key: 'raisehand',
|
key: 'raisehand',
|
||||||
Content: ReactionsMenuButton,
|
Content: _reactionsEnabled ? ReactionsMenuButton : RaiseHandButton,
|
||||||
|
handleClick: _reactionsEnabled ? null : this._onToolbarToggleRaiseHand,
|
||||||
group: 2
|
group: 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1054,6 +1067,23 @@ class Toolbox extends Component<Props> {
|
||||||
this._doToggleFullScreen();
|
this._doToggleFullScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onToolbarToggleRaiseHand: () => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an analytics toolbar event and dispatches an action for toggling
|
||||||
|
* raise hand.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_onToolbarToggleRaiseHand() {
|
||||||
|
sendAnalytics(createToolbarEvent(
|
||||||
|
'raise.hand',
|
||||||
|
{ enable: !this.props._raisedHand }));
|
||||||
|
|
||||||
|
this._doToggleRaiseHand();
|
||||||
|
}
|
||||||
|
|
||||||
_onToolbarToggleScreenshare: () => void;
|
_onToolbarToggleScreenshare: () => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1131,7 +1161,8 @@ class Toolbox extends Component<Props> {
|
||||||
_isMobile,
|
_isMobile,
|
||||||
_overflowMenuVisible,
|
_overflowMenuVisible,
|
||||||
_toolbarButtons,
|
_toolbarButtons,
|
||||||
t
|
t,
|
||||||
|
_reactionsEnabled
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const toolbarAccLabel = 'toolbar.accessibilityLabel.moreActionsMenu';
|
const toolbarAccLabel = 'toolbar.accessibilityLabel.moreActionsMenu';
|
||||||
|
@ -1160,7 +1191,7 @@ class Toolbox extends Component<Props> {
|
||||||
key = 'overflow-menu'
|
key = 'overflow-menu'
|
||||||
onVisibilityChange = { this._onSetOverflowVisible }
|
onVisibilityChange = { this._onSetOverflowVisible }
|
||||||
showMobileReactions = {
|
showMobileReactions = {
|
||||||
overflowMenuButtons.find(({ key }) => key === 'raisehand')
|
_reactionsEnabled && overflowMenuButtons.find(({ key }) => key === 'raisehand')
|
||||||
}>
|
}>
|
||||||
<ul
|
<ul
|
||||||
aria-label = { t(toolbarAccLabel) }
|
aria-label = { t(toolbarAccLabel) }
|
||||||
|
@ -1171,7 +1202,7 @@ class Toolbox extends Component<Props> {
|
||||||
{overflowMenuButtons.map(({ group, key, Content, ...rest }, index, arr) => {
|
{overflowMenuButtons.map(({ group, key, Content, ...rest }, index, arr) => {
|
||||||
const showSeparator = index > 0 && arr[index - 1].group !== group;
|
const showSeparator = index > 0 && arr[index - 1].group !== group;
|
||||||
|
|
||||||
return key !== 'raisehand'
|
return (key !== 'raisehand' || !_reactionsEnabled)
|
||||||
&& <>
|
&& <>
|
||||||
{showSeparator && <Separator key = { `hr${group}` } />}
|
{showSeparator && <Separator key = { `hr${group}` } />}
|
||||||
<Content
|
<Content
|
||||||
|
@ -1218,6 +1249,7 @@ function _mapStateToProps(state) {
|
||||||
const localParticipant = getLocalParticipant(state);
|
const localParticipant = getLocalParticipant(state);
|
||||||
const localVideo = getLocalVideoTrack(state['features/base/tracks']);
|
const localVideo = getLocalVideoTrack(state['features/base/tracks']);
|
||||||
const { clientWidth } = state['features/base/responsive-ui'];
|
const { clientWidth } = state['features/base/responsive-ui'];
|
||||||
|
const { enableReactions } = state['features/base/config'];
|
||||||
|
|
||||||
let desktopSharingDisabledTooltipKey;
|
let desktopSharingDisabledTooltipKey;
|
||||||
|
|
||||||
|
@ -1253,7 +1285,8 @@ function _mapStateToProps(state) {
|
||||||
_screenSharing: isScreenVideoShared(state),
|
_screenSharing: isScreenVideoShared(state),
|
||||||
_toolbarButtons: getToolbarButtons(state),
|
_toolbarButtons: getToolbarButtons(state),
|
||||||
_visible: isToolboxVisible(state),
|
_visible: isToolboxVisible(state),
|
||||||
_visibleButtons: getToolbarButtons(state)
|
_visibleButtons: getToolbarButtons(state),
|
||||||
|
_reactionsEnabled: enableReactions
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue