Selaa lähdekoodia

fix(reactions) Moved reactions behind feature flag

master
robertpin 3 vuotta sitten
vanhempi
commit
2d04f3852c
No account linked to committer's email address

+ 3
- 0
config.js Näytä tiedosto

70
         // callStatsThreshold: 5 // enable callstats for 5% of the users.
70
         // callStatsThreshold: 5 // enable callstats for 5% of the users.
71
     },
71
     },
72
 
72
 
73
+    // Enables reactions feature.
74
+    enableReactions: false,
75
+
73
     // Disables ICE/UDP by filtering out local and remote UDP candidates in
76
     // Disables ICE/UDP by filtering out local and remote UDP candidates in
74
     // signalling.
77
     // signalling.
75
     // webrtcIceUdpDisable: false,
78
     // webrtcIceUdpDisable: false,

+ 5
- 5
css/_reactions-menu.scss Näytä tiedosto

90
 	width: 20%;
90
 	width: 20%;
91
 	bottom: 0;
91
 	bottom: 0;
92
 	left: 40%;
92
 	left: 40%;
93
-	height: 48px;
93
+	height: 0;
94
 }
94
 }
95
 
95
 
96
 .reactions-menu-popup-container,
96
 .reactions-menu-popup-container,
111
 	line-height: 32px;
111
 	line-height: 32px;
112
 	width: 32px;
112
 	width: 32px;
113
 	height: 32px;
113
 	height: 32px;
114
-	top: 32px;
115
-	left: 10px;
114
+	top: 0;
115
+	left: 20px;
116
 	opacity: 0;
116
 	opacity: 0;
117
 	z-index: 1;
117
 	z-index: 1;
118
 
118
 
123
 	@for $i from 1 through $reactionCount {
123
 	@for $i from 1 through $reactionCount {
124
 	&.reaction-#{$i} {
124
 	&.reaction-#{$i} {
125
 		animation: animation-#{$i} 5s forwards ease-in-out;
125
 		animation: animation-#{$i} 5s forwards ease-in-out;
126
-		top: #{random(50, 0)}px;
127
-		left: #{random(-10, 10)}px;
126
+		top: #{random(-40, 10)}px;
127
+		left: #{random(0, 30)}px;
128
 	}
128
 	}
129
 }
129
 }
130
 }
130
 }

+ 6
- 0
react/features/base/flags/constants.js Näytä tiedosto

214
  * Default: disabled (false).
214
  * Default: disabled (false).
215
  */
215
  */
216
 export const WELCOME_PAGE_ENABLED = 'welcomepage.enabled';
216
 export const WELCOME_PAGE_ENABLED = 'welcomepage.enabled';
217
+
218
+/**
219
+ * Flag indicating if the reactions feature should be enabled.
220
+ * Default: disabled (false).
221
+ */
222
+export const REACTIONS_ENABLED = 'reactions.enabled';

+ 14
- 5
react/features/toolbox/components/native/OverflowMenu.js Näytä tiedosto

4
 
4
 
5
 import { ColorSchemeRegistry } from '../../../base/color-scheme';
5
 import { ColorSchemeRegistry } from '../../../base/color-scheme';
6
 import { BottomSheet, hideDialog, isDialogOpen } from '../../../base/dialog';
6
 import { BottomSheet, hideDialog, isDialogOpen } from '../../../base/dialog';
7
+import { getFeatureFlag, REACTIONS_ENABLED } from '../../../base/flags';
7
 import { connect } from '../../../base/redux';
8
 import { connect } from '../../../base/redux';
8
 import { StyleType } from '../../../base/styles';
9
 import { StyleType } from '../../../base/styles';
9
 import { SharedDocumentButton } from '../../../etherpad';
10
 import { SharedDocumentButton } from '../../../etherpad';
22
 import MuteEveryonesVideoButton from '../MuteEveryonesVideoButton';
23
 import MuteEveryonesVideoButton from '../MuteEveryonesVideoButton';
23
 
24
 
24
 import AudioOnlyButton from './AudioOnlyButton';
25
 import AudioOnlyButton from './AudioOnlyButton';
26
+import RaiseHandButton from './RaiseHandButton';
25
 import ScreenSharingButton from './ScreenSharingButton.js';
27
 import ScreenSharingButton from './ScreenSharingButton.js';
26
 import ToggleCameraButton from './ToggleCameraButton';
28
 import ToggleCameraButton from './ToggleCameraButton';
27
 
29
 
50
      */
52
      */
51
     _width: number,
53
     _width: number,
52
 
54
 
55
+    /**
56
+     * Whether or not the reactions feature is enabled.
57
+     */
58
+    _reactionsEnabled: boolean,
59
+
53
     /**
60
     /**
54
      * Used for hiding the dialog when the selection was completed.
61
      * Used for hiding the dialog when the selection was completed.
55
      */
62
      */
102
      * @returns {ReactElement}
109
      * @returns {ReactElement}
103
      */
110
      */
104
     render() {
111
     render() {
105
-        const { _bottomSheetStyles, _width } = this.props;
112
+        const { _bottomSheetStyles, _width, _reactionsEnabled } = this.props;
106
         const toolbarButtons = getMovableButtons(_width);
113
         const toolbarButtons = getMovableButtons(_width);
107
 
114
 
108
         const buttonProps = {
115
         const buttonProps = {
128
         return (
135
         return (
129
             <BottomSheet
136
             <BottomSheet
130
                 onCancel = { this._onCancel }
137
                 onCancel = { this._onCancel }
131
-                renderFooter = { toolbarButtons.has('raisehand')
132
-                    ? null
133
-                    : this._renderReactionMenu }>
138
+                renderFooter = { _reactionsEnabled && !toolbarButtons.has('raisehand')
139
+                    ? this._renderReactionMenu
140
+                    : null }>
134
                 <AudioRouteButton { ...topButtonProps } />
141
                 <AudioRouteButton { ...topButtonProps } />
135
                 <ParticipantsPaneButton { ...buttonProps } />
142
                 <ParticipantsPaneButton { ...buttonProps } />
136
                 {!toolbarButtons.has('invite') && <InviteButton { ...buttonProps } />}
143
                 {!toolbarButtons.has('invite') && <InviteButton { ...buttonProps } />}
137
                 <AudioOnlyButton { ...buttonProps } />
144
                 <AudioOnlyButton { ...buttonProps } />
145
+                {!_reactionsEnabled && !toolbarButtons.has('raisehand') && <RaiseHandButton { ...buttonProps } />}
138
                 <SecurityDialogButton { ...buttonProps } />
146
                 <SecurityDialogButton { ...buttonProps } />
139
                 <ScreenSharingButton { ...buttonProps } />
147
                 <ScreenSharingButton { ...buttonProps } />
140
                 {!toolbarButtons.has('togglecamera') && <ToggleCameraButton { ...buttonProps } />}
148
                 {!toolbarButtons.has('togglecamera') && <ToggleCameraButton { ...buttonProps } />}
194
     return {
202
     return {
195
         _bottomSheetStyles: ColorSchemeRegistry.get(state, 'BottomSheet'),
203
         _bottomSheetStyles: ColorSchemeRegistry.get(state, 'BottomSheet'),
196
         _isOpen: isDialogOpen(state, OverflowMenu_),
204
         _isOpen: isDialogOpen(state, OverflowMenu_),
197
-        _width: state['features/base/responsive-ui'].clientWidth
205
+        _width: state['features/base/responsive-ui'].clientWidth,
206
+        _reactionsEnabled: getFeatureFlag(state, REACTIONS_ENABLED, false)
198
     };
207
     };
199
 }
208
 }
200
 
209
 

+ 105
- 0
react/features/toolbox/components/native/RaiseHandButton.js Näytä tiedosto

1
+// @flow
2
+
3
+import { type Dispatch } from 'redux';
4
+
5
+import {
6
+    createToolbarEvent,
7
+    sendAnalytics
8
+} from '../../../analytics';
9
+import { RAISE_HAND_ENABLED, getFeatureFlag } from '../../../base/flags';
10
+import { translate } from '../../../base/i18n';
11
+import { IconRaisedHand } from '../../../base/icons';
12
+import {
13
+    getLocalParticipant,
14
+    raiseHand
15
+} from '../../../base/participants';
16
+import { connect } from '../../../base/redux';
17
+import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
18
+
19
+/**
20
+ * The type of the React {@code Component} props of {@link RaiseHandButton}.
21
+ */
22
+type Props = AbstractButtonProps & {
23
+
24
+    /**
25
+     * The local participant.
26
+     */
27
+    _localParticipant: Object,
28
+
29
+    /**
30
+     * Whether the participant raused their hand or not.
31
+     */
32
+    _raisedHand: boolean,
33
+
34
+    /**
35
+     * The redux {@code dispatch} function.
36
+     */
37
+    dispatch: Dispatch<any>
38
+};
39
+
40
+/**
41
+ * An implementation of a button to raise or lower hand.
42
+ */
43
+class RaiseHandButton extends AbstractButton<Props, *> {
44
+    accessibilityLabel = 'toolbar.accessibilityLabel.raiseHand';
45
+    icon = IconRaisedHand;
46
+    label = 'toolbar.raiseYourHand';
47
+    toggledLabel = 'toolbar.lowerYourHand';
48
+
49
+    /**
50
+     * Handles clicking / pressing the button.
51
+     *
52
+     * @override
53
+     * @protected
54
+     * @returns {void}
55
+     */
56
+    _handleClick() {
57
+        this._toggleRaisedHand();
58
+    }
59
+
60
+    /**
61
+     * Indicates whether this button is in toggled state or not.
62
+     *
63
+     * @override
64
+     * @protected
65
+     * @returns {boolean}
66
+     */
67
+    _isToggled() {
68
+        return this.props._raisedHand;
69
+    }
70
+
71
+    /**
72
+     * Toggles the rased hand status of the local participant.
73
+     *
74
+     * @returns {void}
75
+     */
76
+    _toggleRaisedHand() {
77
+        const enable = !this.props._raisedHand;
78
+
79
+        sendAnalytics(createToolbarEvent('raise.hand', { enable }));
80
+
81
+        this.props.dispatch(raiseHand(enable));
82
+    }
83
+}
84
+
85
+/**
86
+ * Maps part of the Redux state to the props of this component.
87
+ *
88
+ * @param {Object} state - The Redux state.
89
+ * @param {Object} ownProps - The properties explicitly passed to the component instance.
90
+ * @private
91
+ * @returns {Props}
92
+ */
93
+function _mapStateToProps(state, ownProps): Object {
94
+    const _localParticipant = getLocalParticipant(state);
95
+    const enabled = getFeatureFlag(state, RAISE_HAND_ENABLED, true);
96
+    const { visible = enabled } = ownProps;
97
+
98
+    return {
99
+        _localParticipant,
100
+        _raisedHand: _localParticipant.raisedHand,
101
+        visible
102
+    };
103
+}
104
+
105
+export default translate(connect(_mapStateToProps)(RaiseHandButton));

+ 16
- 5
react/features/toolbox/components/native/Toolbox.js Näytä tiedosto

4
 import { SafeAreaView, View } from 'react-native';
4
 import { SafeAreaView, View } from 'react-native';
5
 
5
 
6
 import { ColorSchemeRegistry } from '../../../base/color-scheme';
6
 import { ColorSchemeRegistry } from '../../../base/color-scheme';
7
+import { getFeatureFlag, REACTIONS_ENABLED } from '../../../base/flags';
7
 import { connect } from '../../../base/redux';
8
 import { connect } from '../../../base/redux';
8
 import { StyleType } from '../../../base/styles';
9
 import { StyleType } from '../../../base/styles';
9
 import { ChatButton } from '../../../chat';
10
 import { ChatButton } from '../../../chat';
16
 import VideoMuteButton from '../VideoMuteButton';
17
 import VideoMuteButton from '../VideoMuteButton';
17
 
18
 
18
 import OverflowMenuButton from './OverflowMenuButton';
19
 import OverflowMenuButton from './OverflowMenuButton';
20
+import RaiseHandButton from './RaiseHandButton';
19
 import ToggleCameraButton from './ToggleCameraButton';
21
 import ToggleCameraButton from './ToggleCameraButton';
20
 import styles from './styles';
22
 import styles from './styles';
21
 
23
 
39
      */
41
      */
40
     _width: number,
42
     _width: number,
41
 
43
 
44
+    /**
45
+     * Whether or not the reactions feature is enabled.
46
+     */
47
+    _reactionsEnabled: boolean,
48
+
42
     /**
49
     /**
43
      * The redux {@code dispatch} function.
50
      * The redux {@code dispatch} function.
44
      */
51
      */
56
         return null;
63
         return null;
57
     }
64
     }
58
 
65
 
59
-    const { _styles, _width } = props;
66
+    const { _styles, _width, _reactionsEnabled } = props;
60
     const { buttonStylesBorderless, hangupButtonStyles, toggledButtonStyles } = _styles;
67
     const { buttonStylesBorderless, hangupButtonStyles, toggledButtonStyles } = _styles;
61
     const additionalButtons = getMovableButtons(_width);
68
     const additionalButtons = getMovableButtons(_width);
62
     const backgroundToggledStyle = {
69
     const backgroundToggledStyle = {
86
                           styles = { buttonStylesBorderless }
93
                           styles = { buttonStylesBorderless }
87
                           toggledStyles = { backgroundToggledStyle } />}
94
                           toggledStyles = { backgroundToggledStyle } />}
88
 
95
 
89
-                { additionalButtons.has('raisehand')
90
-                    && <ReactionsMenuButton
96
+                { additionalButtons.has('raisehand') && (_reactionsEnabled
97
+                    ? <ReactionsMenuButton
98
+                        styles = { buttonStylesBorderless }
99
+                        toggledStyles = { backgroundToggledStyle } />
100
+                    : <RaiseHandButton
91
                         styles = { buttonStylesBorderless }
101
                         styles = { buttonStylesBorderless }
92
-                        toggledStyles = { backgroundToggledStyle } />}
102
+                        toggledStyles = { backgroundToggledStyle } />)}
93
                 {additionalButtons.has('tileview') && <TileViewButton styles = { buttonStylesBorderless } />}
103
                 {additionalButtons.has('tileview') && <TileViewButton styles = { buttonStylesBorderless } />}
94
                 {additionalButtons.has('invite') && <InviteButton styles = { buttonStylesBorderless } />}
104
                 {additionalButtons.has('invite') && <InviteButton styles = { buttonStylesBorderless } />}
95
                 {additionalButtons.has('togglecamera')
105
                 {additionalButtons.has('togglecamera')
119
     return {
129
     return {
120
         _styles: ColorSchemeRegistry.get(state, 'Toolbox'),
130
         _styles: ColorSchemeRegistry.get(state, 'Toolbox'),
121
         _visible: isToolboxVisible(state),
131
         _visible: isToolboxVisible(state),
122
-        _width: state['features/base/responsive-ui'].clientWidth
132
+        _width: state['features/base/responsive-ui'].clientWidth,
133
+        _reactionsEnabled: getFeatureFlag(state, REACTIONS_ENABLED, false)
123
     };
134
     };
124
 }
135
 }
125
 
136
 

+ 83
- 0
react/features/toolbox/components/web/RaiseHandButton.js Näytä tiedosto

1
+// @flow
2
+
3
+import { translate } from '../../../base/i18n';
4
+import { IconRaisedHand } from '../../../base/icons';
5
+import { getLocalParticipant } from '../../../base/participants';
6
+import { connect } from '../../../base/redux';
7
+import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
8
+
9
+type Props = AbstractButtonProps & {
10
+
11
+    /**
12
+     * Whether or not the local participant's hand is raised.
13
+     */
14
+    _raisedHand: boolean,
15
+
16
+    /**
17
+     * External handler for click action.
18
+     */
19
+    handleClick: Function
20
+};
21
+
22
+/**
23
+ * Implementation of a button for toggling raise hand functionality.
24
+ */
25
+class RaiseHandButton extends AbstractButton<Props, *> {
26
+    accessibilityLabel = 'toolbar.accessibilityLabel.raiseHand';
27
+    icon = IconRaisedHand
28
+    label = 'toolbar.raiseYourHand';
29
+    toggledLabel = 'toolbar.lowerYourHand'
30
+
31
+    /**
32
+     * Retrieves tooltip dynamically.
33
+     */
34
+    get tooltip() {
35
+        return this.props._raisedHand ? 'toolbar.lowerYourHand' : 'toolbar.raiseYourHand';
36
+    }
37
+
38
+    /**
39
+     * Required by linter due to AbstractButton overwritten prop being writable.
40
+     *
41
+     * @param {string} value - The value.
42
+     */
43
+    set tooltip(value) {
44
+        return value;
45
+    }
46
+
47
+    /**
48
+     * Handles clicking / pressing the button, and opens the appropriate dialog.
49
+     *
50
+     * @protected
51
+     * @returns {void}
52
+     */
53
+    _handleClick() {
54
+        this.props.handleClick();
55
+    }
56
+
57
+    /**
58
+     * Indicates whether this button is in toggled state or not.
59
+     *
60
+     * @override
61
+     * @protected
62
+     * @returns {boolean}
63
+     */
64
+    _isToggled() {
65
+        return this.props._raisedHand;
66
+    }
67
+}
68
+
69
+/**
70
+ * Function that maps parts of Redux state tree into component props.
71
+ *
72
+ * @param {Object} state - Redux state.
73
+ * @returns {Object}
74
+ */
75
+const mapStateToProps = state => {
76
+    const localParticipant = getLocalParticipant(state);
77
+
78
+    return {
79
+        _raisedHand: localParticipant.raisedHand
80
+    };
81
+};
82
+
83
+export default translate(connect(mapStateToProps)(RaiseHandButton));

+ 68
- 35
react/features/toolbox/components/web/Toolbox.js Näytä tiedosto

85
 import FullscreenButton from './FullscreenButton';
85
 import FullscreenButton from './FullscreenButton';
86
 import OverflowMenuButton from './OverflowMenuButton';
86
 import OverflowMenuButton from './OverflowMenuButton';
87
 import ProfileButton from './ProfileButton';
87
 import ProfileButton from './ProfileButton';
88
+import RaiseHandButton from './RaiseHandButton';
88
 import Separator from './Separator';
89
 import Separator from './Separator';
89
 import ShareDesktopButton from './ShareDesktopButton';
90
 import ShareDesktopButton from './ShareDesktopButton';
90
 import VideoSettingsButton from './VideoSettingsButton';
91
 import VideoSettingsButton from './VideoSettingsButton';
213
     /**
214
     /**
214
      * Returns the selected virtual source object.
215
      * Returns the selected virtual source object.
215
      */
216
      */
216
-     _virtualSource: Object,
217
+    _virtualSource: Object,
218
+
219
+    /**
220
+     * Whether or not reactions feature is enabled.
221
+     */
222
+    _reactionsEnabled: boolean,
217
 
223
 
218
     /**
224
     /**
219
      * Invoked to active other features of the app.
225
      * Invoked to active other features of the app.
259
         this._onToolbarOpenVideoQuality = this._onToolbarOpenVideoQuality.bind(this);
265
         this._onToolbarOpenVideoQuality = this._onToolbarOpenVideoQuality.bind(this);
260
         this._onToolbarToggleChat = this._onToolbarToggleChat.bind(this);
266
         this._onToolbarToggleChat = this._onToolbarToggleChat.bind(this);
261
         this._onToolbarToggleFullScreen = this._onToolbarToggleFullScreen.bind(this);
267
         this._onToolbarToggleFullScreen = this._onToolbarToggleFullScreen.bind(this);
268
+        this._onToolbarToggleRaiseHand = this._onToolbarToggleRaiseHand.bind(this);
262
         this._onToolbarToggleScreenshare = this._onToolbarToggleScreenshare.bind(this);
269
         this._onToolbarToggleScreenshare = this._onToolbarToggleScreenshare.bind(this);
263
         this._onShortcutToggleTileView = this._onShortcutToggleTileView.bind(this);
270
         this._onShortcutToggleTileView = this._onShortcutToggleTileView.bind(this);
264
         this._onEscKey = this._onEscKey.bind(this);
271
         this._onEscKey = this._onEscKey.bind(this);
271
      * @returns {void}
278
      * @returns {void}
272
      */
279
      */
273
     componentDidMount() {
280
     componentDidMount() {
274
-        const { _toolbarButtons, t, dispatch } = this.props;
281
+        const { _toolbarButtons, t, dispatch, _reactionsEnabled } = this.props;
275
         const KEYBOARD_SHORTCUTS = [
282
         const KEYBOARD_SHORTCUTS = [
276
             isToolbarButtonEnabled('videoquality', _toolbarButtons) && {
283
             isToolbarButtonEnabled('videoquality', _toolbarButtons) && {
277
                 character: 'A',
284
                 character: 'A',
320
             }
327
             }
321
         });
328
         });
322
 
329
 
323
-        const REACTION_SHORTCUTS = Object.keys(REACTIONS).map(key => {
324
-            const onShortcutSendReaction = () => {
325
-                dispatch(addReactionToBuffer(key));
326
-                sendAnalytics(createShortcutEvent(
327
-                    `reaction.${key}`
328
-                ));
329
-            };
330
-
331
-            return {
332
-                character: REACTIONS[key].shortcutChar,
333
-                exec: onShortcutSendReaction,
334
-                helpDescription: t(`toolbar.reaction${key.charAt(0).toUpperCase()}${key.slice(1)}`),
335
-                altKey: true
336
-            };
337
-        });
338
-
339
-        REACTION_SHORTCUTS.forEach(shortcut => {
340
-            APP.keyboardshortcut.registerShortcut(
341
-                shortcut.character,
342
-                null,
343
-                shortcut.exec,
344
-                shortcut.helpDescription,
345
-                shortcut.altKey);
346
-        });
330
+        if (_reactionsEnabled) {
331
+            const REACTION_SHORTCUTS = Object.keys(REACTIONS).map(key => {
332
+                const onShortcutSendReaction = () => {
333
+                    dispatch(addReactionToBuffer(key));
334
+                    sendAnalytics(createShortcutEvent(
335
+                        `reaction.${key}`
336
+                    ));
337
+                };
338
+
339
+                return {
340
+                    character: REACTIONS[key].shortcutChar,
341
+                    exec: onShortcutSendReaction,
342
+                    helpDescription: t(`toolbar.reaction${key.charAt(0).toUpperCase()}${key.slice(1)}`),
343
+                    altKey: true
344
+                };
345
+            });
346
+
347
+            REACTION_SHORTCUTS.forEach(shortcut => {
348
+                APP.keyboardshortcut.registerShortcut(
349
+                    shortcut.character,
350
+                    null,
351
+                    shortcut.exec,
352
+                    shortcut.helpDescription,
353
+                    shortcut.altKey);
354
+            });
355
+        }
347
     }
356
     }
348
 
357
 
349
     /**
358
     /**
375
         [ 'A', 'C', 'D', 'R', 'S' ].forEach(letter =>
384
         [ 'A', 'C', 'D', 'R', 'S' ].forEach(letter =>
376
             APP.keyboardshortcut.unregisterShortcut(letter));
385
             APP.keyboardshortcut.unregisterShortcut(letter));
377
 
386
 
378
-        Object.keys(REACTIONS).map(key => REACTIONS[key].shortcutChar)
379
-            .forEach(letter =>
380
-                APP.keyboardshortcut.unregisterShortcut(letter, true));
387
+        if (this.props._reactionsEnabled) {
388
+            Object.keys(REACTIONS).map(key => REACTIONS[key].shortcutChar)
389
+                .forEach(letter =>
390
+                    APP.keyboardshortcut.unregisterShortcut(letter, true));
391
+        }
381
     }
392
     }
382
 
393
 
383
     /**
394
     /**
541
         const {
552
         const {
542
             _feedbackConfigured,
553
             _feedbackConfigured,
543
             _isMobile,
554
             _isMobile,
544
-            _screenSharing
555
+            _screenSharing,
556
+            _reactionsEnabled
545
         } = this.props;
557
         } = this.props;
546
 
558
 
547
         const microphone = {
559
         const microphone = {
578
 
590
 
579
         const raisehand = {
591
         const raisehand = {
580
             key: 'raisehand',
592
             key: 'raisehand',
581
-            Content: ReactionsMenuButton,
593
+            Content: _reactionsEnabled ? ReactionsMenuButton : RaiseHandButton,
594
+            handleClick: _reactionsEnabled ? null : this._onToolbarToggleRaiseHand,
582
             group: 2
595
             group: 2
583
         };
596
         };
584
 
597
 
1054
         this._doToggleFullScreen();
1067
         this._doToggleFullScreen();
1055
     }
1068
     }
1056
 
1069
 
1070
+    _onToolbarToggleRaiseHand: () => void;
1071
+
1072
+    /**
1073
+     * Creates an analytics toolbar event and dispatches an action for toggling
1074
+     * raise hand.
1075
+     *
1076
+     * @private
1077
+     * @returns {void}
1078
+     */
1079
+    _onToolbarToggleRaiseHand() {
1080
+        sendAnalytics(createToolbarEvent(
1081
+            'raise.hand',
1082
+            { enable: !this.props._raisedHand }));
1083
+
1084
+        this._doToggleRaiseHand();
1085
+    }
1086
+
1057
     _onToolbarToggleScreenshare: () => void;
1087
     _onToolbarToggleScreenshare: () => void;
1058
 
1088
 
1059
     /**
1089
     /**
1131
             _isMobile,
1161
             _isMobile,
1132
             _overflowMenuVisible,
1162
             _overflowMenuVisible,
1133
             _toolbarButtons,
1163
             _toolbarButtons,
1134
-            t
1164
+            t,
1165
+            _reactionsEnabled
1135
         } = this.props;
1166
         } = this.props;
1136
 
1167
 
1137
         const toolbarAccLabel = 'toolbar.accessibilityLabel.moreActionsMenu';
1168
         const toolbarAccLabel = 'toolbar.accessibilityLabel.moreActionsMenu';
1160
                                 key = 'overflow-menu'
1191
                                 key = 'overflow-menu'
1161
                                 onVisibilityChange = { this._onSetOverflowVisible }
1192
                                 onVisibilityChange = { this._onSetOverflowVisible }
1162
                                 showMobileReactions = {
1193
                                 showMobileReactions = {
1163
-                                    overflowMenuButtons.find(({ key }) => key === 'raisehand')
1194
+                                    _reactionsEnabled && overflowMenuButtons.find(({ key }) => key === 'raisehand')
1164
                                 }>
1195
                                 }>
1165
                                 <ul
1196
                                 <ul
1166
                                     aria-label = { t(toolbarAccLabel) }
1197
                                     aria-label = { t(toolbarAccLabel) }
1171
                                     {overflowMenuButtons.map(({ group, key, Content, ...rest }, index, arr) => {
1202
                                     {overflowMenuButtons.map(({ group, key, Content, ...rest }, index, arr) => {
1172
                                         const showSeparator = index > 0 && arr[index - 1].group !== group;
1203
                                         const showSeparator = index > 0 && arr[index - 1].group !== group;
1173
 
1204
 
1174
-                                        return key !== 'raisehand'
1205
+                                        return (key !== 'raisehand' || !_reactionsEnabled)
1175
                                             && <>
1206
                                             && <>
1176
                                                 {showSeparator && <Separator key = { `hr${group}` } />}
1207
                                                 {showSeparator && <Separator key = { `hr${group}` } />}
1177
                                                 <Content
1208
                                                 <Content
1218
     const localParticipant = getLocalParticipant(state);
1249
     const localParticipant = getLocalParticipant(state);
1219
     const localVideo = getLocalVideoTrack(state['features/base/tracks']);
1250
     const localVideo = getLocalVideoTrack(state['features/base/tracks']);
1220
     const { clientWidth } = state['features/base/responsive-ui'];
1251
     const { clientWidth } = state['features/base/responsive-ui'];
1252
+    const { enableReactions } = state['features/base/config'];
1221
 
1253
 
1222
     let desktopSharingDisabledTooltipKey;
1254
     let desktopSharingDisabledTooltipKey;
1223
 
1255
 
1253
         _screenSharing: isScreenVideoShared(state),
1285
         _screenSharing: isScreenVideoShared(state),
1254
         _toolbarButtons: getToolbarButtons(state),
1286
         _toolbarButtons: getToolbarButtons(state),
1255
         _visible: isToolboxVisible(state),
1287
         _visible: isToolboxVisible(state),
1256
-        _visibleButtons: getToolbarButtons(state)
1288
+        _visibleButtons: getToolbarButtons(state),
1289
+        _reactionsEnabled: enableReactions
1257
     };
1290
     };
1258
 }
1291
 }
1259
 
1292
 

Loading…
Peruuta
Tallenna